eslint-plugin-react-x 5.2.1-next.1 → 5.2.1-next.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 +264 -26
  2. package/package.json +10 -9
package/dist/index.js CHANGED
@@ -1,18 +1,20 @@
1
1
  import { DEFAULT_ESLINT_REACT_SETTINGS, getSettingsFromContext, toRegExp } from "@eslint-react/shared";
2
2
  import * as ast from "@eslint-react/ast";
3
+ import { findParent, is, isFunction } from "@eslint-react/ast";
3
4
  import * as core from "@eslint-react/core";
4
5
  import { isUseRefCall } from "@eslint-react/core";
5
6
  import { merge } from "@eslint-react/eslint";
6
7
  import { AST_NODE_TYPES } from "@typescript-eslint/types";
7
8
  import { ESLintUtils } from "@typescript-eslint/utils";
8
9
  import { JsxDetectionHint, findParentAttribute, getElementFullType, hasAttribute, isJsxLike } from "@eslint-react/jsx";
9
- import { computeObjectType, findEnclosingAssignmentTarget, isAssignmentTargetEqual, resolve } from "@eslint-react/var";
10
+ import { computeObjectType, isAssignmentTargetEqual, resolve, resolveEnclosingAssignmentTarget } from "@eslint-react/var";
10
11
  import { DefinitionType } from "@typescript-eslint/scope-manager";
11
12
  import { findVariable, getStaticValue } from "@typescript-eslint/utils/ast-utils";
12
13
  import { P, isMatching, match } from "ts-pattern";
13
14
  import { compare } from "compare-versions";
14
15
  import { getConstrainedTypeAtLocation } from "@typescript-eslint/type-utils";
15
16
  import { unionConstituents } from "ts-api-utils";
17
+ import { simpleTraverse } from "@typescript-eslint/typescript-estree";
16
18
  import { snakeCase } from "string-ts";
17
19
 
18
20
  //#region \0rolldown/runtime.js
@@ -142,7 +144,7 @@ const rules$7 = {
142
144
  //#endregion
143
145
  //#region package.json
144
146
  var name$6 = "eslint-plugin-react-x";
145
- var version = "5.2.1-next.1";
147
+ var version = "5.2.1-next.3";
146
148
 
147
149
  //#endregion
148
150
  //#region src/rules/component-hook-factories/lib.ts
@@ -182,6 +184,12 @@ function isHigherOrderComponent(fn) {
182
184
  return false;
183
185
  });
184
186
  }
187
+ function isTestMock$1(node) {
188
+ return node != null && node.type === AST_NODE_TYPES.MemberExpression && node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === "mock";
189
+ }
190
+ function isTestMockCallback$1(node) {
191
+ return node != null && ast.isFunction(node) && node.parent.type === AST_NODE_TYPES.CallExpression && isTestMock$1(node.parent.callee) && node.parent.arguments[1] === node;
192
+ }
185
193
 
186
194
  //#endregion
187
195
  //#region src/utils/create-rule.ts
@@ -221,7 +229,7 @@ function create$48(context) {
221
229
  if (name == null) continue;
222
230
  const parentFn = ast.findParent(node, ast.isFunction);
223
231
  if (parentFn == null) continue;
224
- if (ast.findParent(node, ast.isTestMockCallback) != null) continue;
232
+ if (ast.findParent(node, isTestMockCallback$1) != null) continue;
225
233
  if (isHigherOrderComponent(parentFn)) continue;
226
234
  if (reported.has(node)) continue;
227
235
  context.report({
@@ -234,7 +242,7 @@ function create$48(context) {
234
242
  for (const { name = "unknown", node } of cComponents) {
235
243
  const parentFn = ast.findParent(node, ast.isFunction);
236
244
  if (parentFn == null) continue;
237
- if (ast.findParent(node, ast.isTestMockCallback) != null) continue;
245
+ if (ast.findParent(node, isTestMockCallback$1) != null) continue;
238
246
  if (isHigherOrderComponent(parentFn)) continue;
239
247
  context.report({
240
248
  data: { name },
@@ -244,7 +252,7 @@ function create$48(context) {
244
252
  }
245
253
  for (const { name, node } of hooks) {
246
254
  if (ast.findParent(node, ast.isFunction) == null) continue;
247
- if (ast.findParent(node, ast.isTestMockCallback) != null) continue;
255
+ if (ast.findParent(node, isTestMockCallback$1) != null) continue;
248
256
  if (reported.has(node)) continue;
249
257
  context.report({
250
258
  data: { name },
@@ -2234,7 +2242,7 @@ function create$29(context) {
2234
2242
  if (compare(version, "19.0.0", "<")) return {};
2235
2243
  return merge({ CallExpression(node) {
2236
2244
  if (!core.isForwardRefCall(context, node)) return;
2237
- const id = ast.getFunctionId(node);
2245
+ const id = core.getFunctionId(node);
2238
2246
  const suggest = canFix(context, node) ? [{
2239
2247
  fix: getFix(context, node),
2240
2248
  messageId: "replace"
@@ -2546,7 +2554,7 @@ function create$24(context) {
2546
2554
  });
2547
2555
  return merge(visitor, { "Program:exit"(program) {
2548
2556
  for (const { displayName, flag, node } of api.getAllComponents(program)) {
2549
- const id = ast.getFunctionId(node);
2557
+ const id = core.getFunctionId(node);
2550
2558
  const isMemoOrForwardRef = (flag & (core.FunctionComponentFlag.ForwardRef | core.FunctionComponentFlag.Memo)) > 0n;
2551
2559
  if (id != null) continue;
2552
2560
  if (!isMemoOrForwardRef) continue;
@@ -2587,7 +2595,7 @@ function create$23(context) {
2587
2595
  },
2588
2596
  "Program:exit"() {
2589
2597
  for (const call of createCalls) {
2590
- const id = findEnclosingAssignmentTarget(call);
2598
+ const id = resolveEnclosingAssignmentTarget(call);
2591
2599
  if (id == null) {
2592
2600
  context.report({
2593
2601
  messageId: "default",
@@ -2636,6 +2644,21 @@ function report(context) {
2636
2644
  return context.report(descriptor);
2637
2645
  };
2638
2646
  }
2647
+ /**
2648
+ * Gets the nested return statements in the node that are within the same function
2649
+ * @param node The AST node
2650
+ * @returns The nested return statements in the node
2651
+ */
2652
+ function getNestedReturnStatements(node) {
2653
+ const statements = [];
2654
+ const boundaryNode = isFunction(node) ? node : findParent(node, isFunction);
2655
+ simpleTraverse(node, { enter(node) {
2656
+ if (node.type !== AST_NODE_TYPES.ReturnStatement) return;
2657
+ if (findParent(node, isFunction) !== boundaryNode) return;
2658
+ statements.push(node);
2659
+ } });
2660
+ return statements;
2661
+ }
2639
2662
 
2640
2663
  //#endregion
2641
2664
  //#region src/rules/no-missing-key/no-missing-key.ts
@@ -2678,7 +2701,7 @@ function create$22(context) {
2678
2701
  }
2679
2702
  function checkBlock(node) {
2680
2703
  const descriptors = [];
2681
- for (const stmt of ast.getNestedReturnStatements(node)) {
2704
+ for (const stmt of getNestedReturnStatements(node)) {
2682
2705
  if (stmt.argument == null) continue;
2683
2706
  const desc = check(stmt.argument);
2684
2707
  if (desc == null) continue;
@@ -2722,6 +2745,32 @@ function create$22(context) {
2722
2745
  });
2723
2746
  }
2724
2747
 
2748
+ //#endregion
2749
+ //#region src/rules/no-misused-capture-owner-stack/lib.ts
2750
+ /**
2751
+ * Check if the given node is a member expression that accesses `process.env.NODE_ENV`
2752
+ * @param node The AST node
2753
+ * @returns True if the node is a member expression that accesses `process.env.NODE_ENV`, false otherwise
2754
+ */
2755
+ function isProcessEnvNodeEnv(node) {
2756
+ return node != null && node.type === AST_NODE_TYPES.MemberExpression && node.object.type === AST_NODE_TYPES.MemberExpression && node.object.object.type === AST_NODE_TYPES.Identifier && node.object.object.name === "process" && node.object.property.type === AST_NODE_TYPES.Identifier && node.object.property.name === "env" && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === "NODE_ENV";
2757
+ }
2758
+ /**
2759
+ * Check if the given node is a binary expression that compares `process.env.NODE_ENV` with a string literal.
2760
+ * @param node The AST node
2761
+ * @param operator The operator used in the comparison
2762
+ * @param value The string literal value to compare against
2763
+ * @returns True if the node is a binary expression that compares `process.env.NODE_ENV` with the specified value, false otherwise
2764
+ */
2765
+ function isProcessEnvNodeEnvCompare(node, operator, value) {
2766
+ if (node == null) return false;
2767
+ if (node.type !== AST_NODE_TYPES.BinaryExpression) return false;
2768
+ if (node.operator !== operator) return false;
2769
+ if (isProcessEnvNodeEnv(node.left) && ast.isLiteral(node.right, "string")) return node.right.value === value;
2770
+ if (ast.isLiteral(node.left, "string") && isProcessEnvNodeEnv(node.right)) return node.left.value === value;
2771
+ return false;
2772
+ }
2773
+
2725
2774
  //#endregion
2726
2775
  //#region src/rules/no-misused-capture-owner-stack/no-misused-capture-owner-stack.ts
2727
2776
  const RULE_NAME$21 = "no-misused-capture-owner-stack";
@@ -2765,7 +2814,7 @@ function create$21(context) {
2765
2814
  }
2766
2815
  function isDevelopmentOnlyCheck(node) {
2767
2816
  if (node.type !== AST_NODE_TYPES.IfStatement) return false;
2768
- return ast.isProcessEnvNodeEnvCompare(node.test, "!==", "production");
2817
+ return isProcessEnvNodeEnvCompare(node.test, "!==", "production");
2769
2818
  }
2770
2819
 
2771
2820
  //#endregion
@@ -3013,12 +3062,21 @@ function create$16(context) {
3013
3062
  }
3014
3063
 
3015
3064
  //#endregion
3016
- //#region src/rules/no-unnecessary-use-prefix/no-unnecessary-use-prefix.ts
3017
- const RULE_NAME$15 = "no-unnecessary-use-prefix";
3065
+ //#region src/rules/no-unnecessary-use-prefix/lib.ts
3018
3066
  const WELL_KNOWN_HOOKS = ["useMDXComponents"];
3019
3067
  function containsUseComments(context, node) {
3020
3068
  return context.sourceCode.getCommentsInside(node).some(({ value }) => /use\([\s\S]*?\)/u.test(value) || /use[A-Z0-9]\w*\([\s\S]*?\)/u.test(value));
3021
3069
  }
3070
+ function isTestMock(node) {
3071
+ return node != null && node.type === AST_NODE_TYPES.MemberExpression && node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === "mock";
3072
+ }
3073
+ function isTestMockCallback(node) {
3074
+ return node != null && ast.isFunction(node) && node.parent.type === AST_NODE_TYPES.CallExpression && isTestMock(node.parent.callee) && node.parent.arguments[1] === node;
3075
+ }
3076
+
3077
+ //#endregion
3078
+ //#region src/rules/no-unnecessary-use-prefix/no-unnecessary-use-prefix.ts
3079
+ const RULE_NAME$15 = "no-unnecessary-use-prefix";
3022
3080
  var no_unnecessary_use_prefix_default = createRule({
3023
3081
  meta: {
3024
3082
  type: "problem",
@@ -3036,10 +3094,10 @@ function create$15(context) {
3036
3094
  for (const { id, name, hookCalls, node } of api.getAllHooks(program)) {
3037
3095
  if (name == null) continue;
3038
3096
  if (hookCalls.length > 0) continue;
3039
- if (ast.isFunctionEmpty(node)) continue;
3097
+ if (core.isFunctionEmpty(node)) continue;
3040
3098
  if (WELL_KNOWN_HOOKS.includes(name)) continue;
3041
3099
  if (containsUseComments(context, node)) continue;
3042
- if (ast.findParent(node, ast.isTestMockCallback) != null) continue;
3100
+ if (ast.findParent(node, isTestMockCallback) != null) continue;
3043
3101
  context.report({
3044
3102
  data: { name },
3045
3103
  messageId: "default",
@@ -3150,7 +3208,7 @@ var no_unstable_context_value_default = createRule({
3150
3208
  function create$11(context) {
3151
3209
  const { compilationMode, version } = getSettingsFromContext(context);
3152
3210
  if (compilationMode === "infer" || compilationMode === "all") return {};
3153
- if (compilationMode === "annotation" && ast.isDirectiveInFile(context.sourceCode.ast, "use memo")) return {};
3211
+ if (compilationMode === "annotation" && ast.isFileHasDirective(context.sourceCode.ast, "use memo")) return {};
3154
3212
  const isReact18OrBelow = compare(version, "19.0.0", "<");
3155
3213
  const { api, visitor } = core.getFunctionComponentCollector(context);
3156
3214
  const constructions = /* @__PURE__ */ new WeakMap();
@@ -3161,7 +3219,7 @@ function create$11(context) {
3161
3219
  if (!isContextName(selfName, isReact18OrBelow)) return;
3162
3220
  const enclosingFunction = ast.findParent(node, ast.isFunction);
3163
3221
  if (enclosingFunction == null) return;
3164
- if (compilationMode === "annotation" && ast.isDirectiveInFunction(enclosingFunction, "use memo")) return;
3222
+ if (compilationMode === "annotation" && core.isFunctionHasDirective(enclosingFunction, "use memo")) return;
3165
3223
  const attribute = node.attributes.find((attribute) => attribute.type === AST_NODE_TYPES.JSXAttribute && attribute.name.name === "value");
3166
3224
  if (attribute == null || !("value" in attribute)) return;
3167
3225
  const value = attribute.value;
@@ -3231,7 +3289,7 @@ function extractIdentifier(node) {
3231
3289
  function create$10(context, [options]) {
3232
3290
  const { compilationMode } = getSettingsFromContext(context);
3233
3291
  if (compilationMode === "infer" || compilationMode === "all") return {};
3234
- if (compilationMode === "annotation" && ast.isDirectiveInFile(context.sourceCode.ast, "use memo")) return {};
3292
+ if (compilationMode === "annotation" && ast.isFileHasDirective(context.sourceCode.ast, "use memo")) return {};
3235
3293
  const { api, visitor } = core.getFunctionComponentCollector(context);
3236
3294
  const declarators = /* @__PURE__ */ new WeakMap();
3237
3295
  const { safeDefaultProps = [] } = options;
@@ -3323,7 +3381,7 @@ function create$9(context) {
3323
3381
  function classExit() {
3324
3382
  const currentClass = classStack.pop();
3325
3383
  if (currentClass == null || !core.isClassComponent(currentClass)) return;
3326
- const id = ast.getClassId(currentClass);
3384
+ const id = core.getClassId(currentClass);
3327
3385
  const defs = propertyDefs.get(currentClass);
3328
3386
  const usages = propertyUsages.get(currentClass);
3329
3387
  if (defs == null) return;
@@ -6198,6 +6256,91 @@ function last(array) {
6198
6256
  return array[array.length - 1];
6199
6257
  }
6200
6258
 
6259
+ //#endregion
6260
+ //#region src/rules/set-state-in-effect/lib.ts
6261
+ /**
6262
+ * Get all nested identifiers in a expression like node
6263
+ * @param node The node to get the nested identifiers from
6264
+ * @returns All nested identifiers
6265
+ */
6266
+ function getNestedIdentifiers(node) {
6267
+ const identifiers = [];
6268
+ if (node.type === AST_NODE_TYPES.Identifier) identifiers.push(node);
6269
+ if ("arguments" in node) {
6270
+ const chunk = node.arguments.flatMap(getNestedIdentifiers);
6271
+ identifiers.push(...chunk);
6272
+ }
6273
+ if ("elements" in node) {
6274
+ const chunk = node.elements.filter((x) => x != null).flatMap(getNestedIdentifiers);
6275
+ identifiers.push(...chunk);
6276
+ }
6277
+ if ("properties" in node) {
6278
+ const chunk = node.properties.flatMap(getNestedIdentifiers);
6279
+ identifiers.push(...chunk);
6280
+ }
6281
+ if ("expressions" in node) {
6282
+ const chunk = node.expressions.flatMap(getNestedIdentifiers);
6283
+ identifiers.push(...chunk);
6284
+ }
6285
+ if ("left" in node) {
6286
+ const chunk = getNestedIdentifiers(node.left);
6287
+ identifiers.push(...chunk);
6288
+ }
6289
+ if ("right" in node) {
6290
+ const chunk = getNestedIdentifiers(node.right);
6291
+ identifiers.push(...chunk);
6292
+ }
6293
+ if (node.type === AST_NODE_TYPES.Property) {
6294
+ const chunk = getNestedIdentifiers(node.value);
6295
+ identifiers.push(...chunk);
6296
+ }
6297
+ if (node.type === AST_NODE_TYPES.SpreadElement) {
6298
+ const chunk = getNestedIdentifiers(node.argument);
6299
+ identifiers.push(...chunk);
6300
+ }
6301
+ if (node.type === AST_NODE_TYPES.MemberExpression) {
6302
+ identifiers.push(...getNestedIdentifiers(node.object));
6303
+ if (node.computed) identifiers.push(...getNestedIdentifiers(node.property));
6304
+ }
6305
+ if (node.type === AST_NODE_TYPES.UnaryExpression) {
6306
+ const chunk = getNestedIdentifiers(node.argument);
6307
+ identifiers.push(...chunk);
6308
+ }
6309
+ if (node.type === AST_NODE_TYPES.ChainExpression) {
6310
+ const chunk = getNestedIdentifiers(node.expression);
6311
+ identifiers.push(...chunk);
6312
+ }
6313
+ if (node.type === AST_NODE_TYPES.TSNonNullExpression) {
6314
+ const chunk = getNestedIdentifiers(node.expression);
6315
+ identifiers.push(...chunk);
6316
+ }
6317
+ if (node.type === AST_NODE_TYPES.TSAsExpression) {
6318
+ const chunk = getNestedIdentifiers(node.expression);
6319
+ identifiers.push(...chunk);
6320
+ }
6321
+ if (node.type === AST_NODE_TYPES.TSSatisfiesExpression) {
6322
+ const chunk = getNestedIdentifiers(node.expression);
6323
+ identifiers.push(...chunk);
6324
+ }
6325
+ if (node.type === AST_NODE_TYPES.ConditionalExpression) {
6326
+ identifiers.push(...getNestedIdentifiers(node.test));
6327
+ identifiers.push(...getNestedIdentifiers(node.consequent));
6328
+ identifiers.push(...getNestedIdentifiers(node.alternate));
6329
+ }
6330
+ if (node.type === AST_NODE_TYPES.AwaitExpression) identifiers.push(...getNestedIdentifiers(node.argument));
6331
+ if (node.type === AST_NODE_TYPES.YieldExpression && node.argument != null) identifiers.push(...getNestedIdentifiers(node.argument));
6332
+ if (node.type === AST_NODE_TYPES.UpdateExpression) identifiers.push(...getNestedIdentifiers(node.argument));
6333
+ if (node.type === AST_NODE_TYPES.CallExpression || node.type === AST_NODE_TYPES.NewExpression) identifiers.push(...getNestedIdentifiers(node.callee));
6334
+ if (node.type === AST_NODE_TYPES.TaggedTemplateExpression) {
6335
+ identifiers.push(...getNestedIdentifiers(node.tag));
6336
+ identifiers.push(...getNestedIdentifiers(node.quasi));
6337
+ }
6338
+ if (node.type === AST_NODE_TYPES.ImportExpression) identifiers.push(...getNestedIdentifiers(node.source));
6339
+ if (node.type === AST_NODE_TYPES.TSTypeAssertion) identifiers.push(...getNestedIdentifiers(node.expression));
6340
+ if (node.type === AST_NODE_TYPES.TSInstantiationExpression) identifiers.push(...getNestedIdentifiers(node.expression));
6341
+ return identifiers;
6342
+ }
6343
+
6201
6344
  //#endregion
6202
6345
  //#region src/rules/set-state-in-effect/set-state-in-effect.ts
6203
6346
  const RULE_NAME$4 = "set-state-in-effect";
@@ -6306,7 +6449,7 @@ function create$4(context) {
6306
6449
  if (init == null) continue;
6307
6450
  switch (true) {
6308
6451
  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;
6309
- case init.type === AST_NODE_TYPES.CallExpression && isUseRefCall(context, init): return true;
6452
+ case init.type === AST_NODE_TYPES.CallExpression && core.isUseRefCall(context, init): return true;
6310
6453
  }
6311
6454
  }
6312
6455
  return false;
@@ -6342,7 +6485,7 @@ function create$4(context) {
6342
6485
  switch (n.type) {
6343
6486
  case AST_NODE_TYPES.Identifier: return isInitializedFromRef(n.name, context.sourceCode.getScope(n));
6344
6487
  case AST_NODE_TYPES.MemberExpression: return isUsingRefValue(n.object);
6345
- case AST_NODE_TYPES.CallExpression: return isUsingRefValue(n.callee) || ast.getNestedIdentifiers(n).some(isUsingRefValue);
6488
+ case AST_NODE_TYPES.CallExpression: return isUsingRefValue(n.callee) || getNestedIdentifiers(n).some(isUsingRefValue);
6346
6489
  default: return false;
6347
6490
  }
6348
6491
  };
@@ -6365,7 +6508,7 @@ function create$4(context) {
6365
6508
  }
6366
6509
  }).with("useEffect", () => {
6367
6510
  if (ast.isFunction(node.arguments.at(0))) return;
6368
- setupFnIds.push(...ast.getNestedIdentifiers(node));
6511
+ setupFnIds.push(...getNestedIdentifiers(node));
6369
6512
  }).with("other", () => {
6370
6513
  if (entry.node !== setupFunction) return;
6371
6514
  trackedFnCalls.push(node);
@@ -6505,7 +6648,7 @@ function create$3(context) {
6505
6648
  return false;
6506
6649
  }
6507
6650
  function isComponentOrHookLikeFunction(node) {
6508
- const id = ast.getFunctionId(node);
6651
+ const id = core.getFunctionId(node);
6509
6652
  if (id == null) return false;
6510
6653
  if (id.type === AST_NODE_TYPES.Identifier) return core.isFunctionComponentName(id.name) || core.isHookName(id.name);
6511
6654
  if (id.type === AST_NODE_TYPES.MemberExpression && id.property.type === AST_NODE_TYPES.Identifier) return core.isFunctionComponentName(id.property.name) || core.isHookName(id.property.name);
@@ -6683,7 +6826,7 @@ function create$1(context) {
6683
6826
  if (!ast.isFunction(callbackArg)) return;
6684
6827
  if (callbackArg.type === AST_NODE_TYPES.ArrowFunctionExpression && callbackArg.body.type !== AST_NODE_TYPES.BlockStatement) return;
6685
6828
  if (callbackArg.body.type !== AST_NODE_TYPES.BlockStatement) return;
6686
- const returnStatements = ast.getNestedReturnStatements(callbackArg);
6829
+ const returnStatements = getNestedReturnStatements(callbackArg);
6687
6830
  if (returnStatements.length === 0) {
6688
6831
  context.report({
6689
6832
  messageId: "missingReturnValue",
@@ -6698,6 +6841,101 @@ function create$1(context) {
6698
6841
  } });
6699
6842
  }
6700
6843
 
6844
+ //#endregion
6845
+ //#region src/rules/use-state/lib.ts
6846
+ /**
6847
+ * Get all nested expressions of type T in an expression like node
6848
+ * @param type The type of the expression to retrieve within the node
6849
+ * @returns A partially applied function bound to a predicate of type AST. The returned function can be called passing a
6850
+ * node, and it will return an array of all nested expressions of type AST.
6851
+ */
6852
+ function getNestedExpressionsOfType(type) {
6853
+ const isNodeOfType = is(type);
6854
+ const recurse = (node) => {
6855
+ const expressions = [];
6856
+ if (isNodeOfType(node)) expressions.push(node);
6857
+ if ("arguments" in node) {
6858
+ const chunk = node.arguments.flatMap(recurse);
6859
+ expressions.push(...chunk);
6860
+ }
6861
+ if ("expression" in node && node.expression !== true && node.expression !== false) {
6862
+ const chunk = recurse(node.expression);
6863
+ expressions.push(...chunk);
6864
+ }
6865
+ if ("left" in node) {
6866
+ const chunk = recurse(node.left);
6867
+ expressions.push(...chunk);
6868
+ }
6869
+ if ("right" in node) {
6870
+ const chunk = recurse(node.right);
6871
+ expressions.push(...chunk);
6872
+ }
6873
+ if ("test" in node && node.test != null) {
6874
+ const chunk = recurse(node.test);
6875
+ expressions.push(...chunk);
6876
+ }
6877
+ if ("consequent" in node) {
6878
+ const chunk = Array.isArray(node.consequent) ? node.consequent.flatMap(recurse) : recurse(node.consequent);
6879
+ expressions.push(...chunk);
6880
+ }
6881
+ if ("alternate" in node && node.alternate != null) {
6882
+ const chunk = Array.isArray(node.alternate) ? node.alternate.flatMap(recurse) : recurse(node.alternate);
6883
+ expressions.push(...chunk);
6884
+ }
6885
+ if ("elements" in node) {
6886
+ const chunk = node.elements.filter((x) => x != null).flatMap(recurse);
6887
+ expressions.push(...chunk);
6888
+ }
6889
+ if ("properties" in node) {
6890
+ const chunk = node.properties.flatMap(recurse);
6891
+ expressions.push(...chunk);
6892
+ }
6893
+ if ("expressions" in node) {
6894
+ const chunk = node.expressions.flatMap(recurse);
6895
+ expressions.push(...chunk);
6896
+ }
6897
+ if (node.type === AST_NODE_TYPES.Property) {
6898
+ const chunk = recurse(node.value);
6899
+ expressions.push(...chunk);
6900
+ }
6901
+ if (node.type === AST_NODE_TYPES.SpreadElement) {
6902
+ const chunk = recurse(node.argument);
6903
+ expressions.push(...chunk);
6904
+ }
6905
+ if (node.type === AST_NODE_TYPES.MemberExpression) {
6906
+ expressions.push(...recurse(node.object));
6907
+ if (node.computed) expressions.push(...recurse(node.property));
6908
+ }
6909
+ if (node.type === AST_NODE_TYPES.UnaryExpression) {
6910
+ const chunk = recurse(node.argument);
6911
+ expressions.push(...chunk);
6912
+ }
6913
+ if (node.type === AST_NODE_TYPES.AwaitExpression) expressions.push(...recurse(node.argument));
6914
+ if (node.type === AST_NODE_TYPES.YieldExpression && node.argument != null) expressions.push(...recurse(node.argument));
6915
+ if (node.type === AST_NODE_TYPES.UpdateExpression) expressions.push(...recurse(node.argument));
6916
+ if (node.type === AST_NODE_TYPES.CallExpression || node.type === AST_NODE_TYPES.NewExpression) expressions.push(...recurse(node.callee));
6917
+ if (node.type === AST_NODE_TYPES.TaggedTemplateExpression) {
6918
+ expressions.push(...recurse(node.tag));
6919
+ expressions.push(...recurse(node.quasi));
6920
+ }
6921
+ if (node.type === AST_NODE_TYPES.ImportExpression) expressions.push(...recurse(node.source));
6922
+ return expressions;
6923
+ };
6924
+ return recurse;
6925
+ }
6926
+ /**
6927
+ * Get all nested new expressions in an expression like node
6928
+ * @param node The node to get the nested new expressions from
6929
+ * @returns All nested new expressions
6930
+ */
6931
+ const getNestedNewExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.NewExpression);
6932
+ /**
6933
+ * Get all nested call expressions in a expression like node
6934
+ * @param node The node to get the nested call expressions from
6935
+ * @returns All nested call expressions
6936
+ */
6937
+ const getNestedCallExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.CallExpression);
6938
+
6701
6939
  //#endregion
6702
6940
  //#region src/rules/use-state/use-state.ts
6703
6941
  const RULE_NAME = "use-state";
@@ -6752,7 +6990,7 @@ function create(context) {
6752
6990
  if (enforceLazyInitialization) {
6753
6991
  const [useStateInput] = node.arguments;
6754
6992
  if (useStateInput != null) {
6755
- for (const expr of ast.getNestedNewExpressions(useStateInput)) {
6993
+ for (const expr of getNestedNewExpressions(useStateInput)) {
6756
6994
  if (!("name" in expr.callee)) continue;
6757
6995
  if (LAZY_INIT_ALLOW_LIST.includes(expr.callee.name)) continue;
6758
6996
  if (ast.findParent(expr, (n) => core.isUseCall(context, n)) != null) continue;
@@ -6761,7 +6999,7 @@ function create(context) {
6761
6999
  node: expr
6762
7000
  });
6763
7001
  }
6764
- for (const expr of ast.getNestedCallExpressions(useStateInput)) {
7002
+ for (const expr of getNestedCallExpressions(useStateInput)) {
6765
7003
  if (!("name" in expr.callee)) continue;
6766
7004
  if (core.isHookName(expr.callee.name)) continue;
6767
7005
  if (LAZY_INIT_ALLOW_LIST.includes(expr.callee.name)) continue;
@@ -6781,7 +7019,7 @@ function create(context) {
6781
7019
  });
6782
7020
  return;
6783
7021
  }
6784
- const id = findEnclosingAssignmentTarget(node);
7022
+ const id = resolveEnclosingAssignmentTarget(node);
6785
7023
  if (id?.type !== AST_NODE_TYPES.ArrayPattern) {
6786
7024
  if (!enforceAssignment) return;
6787
7025
  context.report({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-x",
3
- "version": "5.2.1-next.1",
3
+ "version": "5.2.1-next.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",
@@ -40,17 +40,18 @@
40
40
  "@typescript-eslint/scope-manager": "^8.58.1",
41
41
  "@typescript-eslint/type-utils": "^8.58.1",
42
42
  "@typescript-eslint/types": "^8.58.1",
43
+ "@typescript-eslint/typescript-estree": "^8.58.1",
43
44
  "@typescript-eslint/utils": "^8.58.1",
44
45
  "compare-versions": "^6.1.1",
45
46
  "string-ts": "^2.3.1",
46
47
  "ts-api-utils": "^2.5.0",
47
48
  "ts-pattern": "^5.9.0",
48
- "@eslint-react/ast": "5.2.1-next.1",
49
- "@eslint-react/core": "5.2.1-next.1",
50
- "@eslint-react/eslint": "5.2.1-next.1",
51
- "@eslint-react/shared": "5.2.1-next.1",
52
- "@eslint-react/jsx": "5.2.1-next.1",
53
- "@eslint-react/var": "5.2.1-next.1"
49
+ "@eslint-react/ast": "5.2.1-next.3",
50
+ "@eslint-react/eslint": "5.2.1-next.3",
51
+ "@eslint-react/shared": "5.2.1-next.3",
52
+ "@eslint-react/jsx": "5.2.1-next.3",
53
+ "@eslint-react/var": "5.2.1-next.3",
54
+ "@eslint-react/core": "5.2.1-next.3"
54
55
  },
55
56
  "devDependencies": {
56
57
  "@types/react": "^19.2.14",
@@ -58,8 +59,8 @@
58
59
  "eslint": "^10.2.0",
59
60
  "tsdown": "^0.21.7",
60
61
  "tsl-dx": "^0.10.3",
61
- "@local/eff": "3.0.0-beta.72",
62
- "@local/configs": "0.0.0"
62
+ "@local/configs": "0.0.0",
63
+ "@local/eff": "3.0.0-beta.72"
63
64
  },
64
65
  "peerDependencies": {
65
66
  "eslint": "^10.2.0",