eslint-plugin-react-x 3.0.0-beta.63 → 3.0.0-beta.64

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 +48 -89
  2. package/package.json +7 -7
package/dist/index.js CHANGED
@@ -5,13 +5,13 @@ import { ESLintUtils } from "@typescript-eslint/utils";
5
5
  import { P, isMatching, match } from "ts-pattern";
6
6
  import ts from "typescript";
7
7
  import { AST_NODE_TYPES } from "@typescript-eslint/types";
8
- import { constFalse, constTrue, constVoid, flow, getOrElseUpdate, identity, not, unit } from "@eslint-react/eff";
8
+ import { computeObjectType, findEnclosingAssignmentTarget, isAssignmentTargetEqual, resolve } from "@eslint-react/var";
9
9
  import { DefinitionType } from "@typescript-eslint/scope-manager";
10
10
  import { findVariable, getStaticValue, isIdentifier, isVariableDeclarator } from "@typescript-eslint/utils/ast-utils";
11
+ import { constFalse, constTrue, constVoid, flow, getOrElseUpdate, identity, not } from "@eslint-react/eff";
11
12
  import { compare } from "compare-versions";
12
13
  import { getConstrainedTypeAtLocation } from "@typescript-eslint/type-utils";
13
14
  import { unionConstituents } from "ts-api-utils";
14
- import { computeObjectType, findEnclosingAssignmentTarget, isAssignmentTargetEqual } from "@eslint-react/var";
15
15
  import { snakeCase } from "string-ts";
16
16
 
17
17
  //#region \0rolldown/runtime.js
@@ -69,7 +69,7 @@ const rules$7 = {
69
69
  //#endregion
70
70
  //#region package.json
71
71
  var name$6 = "eslint-plugin-react-x";
72
- var version = "3.0.0-beta.63";
72
+ var version = "3.0.0-beta.64";
73
73
 
74
74
  //#endregion
75
75
  //#region src/utils/create-rule.ts
@@ -1289,7 +1289,7 @@ function create$61(context) {
1289
1289
  * @returns True if `id` is a state variable, false otherwise.
1290
1290
  */
1291
1291
  function isStateValue(id) {
1292
- const initNode = resolve$4(findVariable(context.sourceCode.getScope(id), id));
1292
+ const initNode = resolve(context, id);
1293
1293
  if (initNode == null || initNode.type !== AST_NODE_TYPES.CallExpression) return false;
1294
1294
  if (!isUseStateCall(initNode)) return false;
1295
1295
  const declarator = initNode.parent;
@@ -1388,13 +1388,6 @@ function create$61(context) {
1388
1388
  }
1389
1389
  });
1390
1390
  }
1391
- function resolve$4(v) {
1392
- if (v == null) return unit;
1393
- const def = v.defs.at(0);
1394
- if (def == null) return unit;
1395
- if ("init" in def.node && def.node.init != null && !("declarations" in def.node.init)) return def.node.init;
1396
- return def.node;
1397
- }
1398
1391
 
1399
1392
  //#endregion
1400
1393
  //#region src/rules/jsx-dollar/jsx-dollar.ts
@@ -1839,18 +1832,18 @@ function getIndexParamPosition(methodName) {
1839
1832
  }
1840
1833
  function getMapIndexParamName(context, node) {
1841
1834
  const { callee } = node;
1842
- if (callee.type !== AST_NODE_TYPES.MemberExpression) return unit;
1843
- if (callee.property.type !== AST_NODE_TYPES.Identifier) return unit;
1835
+ if (callee.type !== AST_NODE_TYPES.MemberExpression) return null;
1836
+ if (callee.property.type !== AST_NODE_TYPES.Identifier) return null;
1844
1837
  const { name } = callee.property;
1845
1838
  const indexPosition = getIndexParamPosition(name);
1846
- if (indexPosition === -1) return unit;
1839
+ if (indexPosition === -1) return null;
1847
1840
  const callbackArg = node.arguments[core.isChildrenMap(context, callee) || core.isChildrenForEach(context, callee) ? 1 : 0];
1848
- if (callbackArg == null) return unit;
1849
- if (!ast.isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(callbackArg)) return unit;
1841
+ if (callbackArg == null) return null;
1842
+ if (!ast.isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(callbackArg)) return null;
1850
1843
  const { params } = callbackArg;
1851
- if (params.length < indexPosition + 1) return unit;
1844
+ if (params.length < indexPosition + 1) return null;
1852
1845
  const param = params.at(indexPosition);
1853
- return param != null && "name" in param ? param.name : unit;
1846
+ return param != null && "name" in param ? param.name : null;
1854
1847
  }
1855
1848
  function getIdentifiersFromBinaryExpression(side) {
1856
1849
  if (side.type === AST_NODE_TYPES.Identifier) return [side];
@@ -2574,12 +2567,12 @@ function create$33(context) {
2574
2567
  /**
2575
2568
  * Recursively inspects a node to find potential leaked conditional rendering
2576
2569
  * @param node The AST node to inspect
2577
- * @returns A report descriptor if a problem is found, otherwise `unit`
2570
+ * @returns A report descriptor if a problem is found, otherwise `null`
2578
2571
  */
2579
2572
  function getReportDescriptor(node) {
2580
- if (node == null) return unit;
2573
+ if (node == null) return null;
2581
2574
  if (ast.is(AST_NODE_TYPES.JSXExpressionContainer)(node)) return getReportDescriptor(node.expression);
2582
- if (ast.isJSX(node)) return unit;
2575
+ if (ast.isJSX(node)) return null;
2583
2576
  if (ast.isTypeExpression(node)) return getReportDescriptor(node.expression);
2584
2577
  return match(node).with({
2585
2578
  type: AST_NODE_TYPES.LogicalExpression,
@@ -2603,8 +2596,8 @@ function create$33(context) {
2603
2596
  return getReportDescriptor(consequent) ?? getReportDescriptor(alternate);
2604
2597
  }).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
2605
2598
  const variableDefNode = findVariable(context.sourceCode.getScope(n), n.name)?.defs.at(0)?.node;
2606
- return match(variableDefNode).with({ init: P.select({ type: P.not(AST_NODE_TYPES.VariableDeclaration) }) }, getReportDescriptor).otherwise(() => unit);
2607
- }).otherwise(() => unit);
2599
+ return match(variableDefNode).with({ init: P.select({ type: P.not(AST_NODE_TYPES.VariableDeclaration) }) }, getReportDescriptor).otherwise(() => null);
2600
+ }).otherwise(() => null);
2608
2601
  }
2609
2602
  return defineRuleListener({ JSXExpressionContainer: flow(getReportDescriptor, report(context)) });
2610
2603
  }
@@ -3145,13 +3138,13 @@ function create$22(context) {
3145
3138
  const [cbk, ...rest] = context.sourceCode.getDeclaredVariables(node);
3146
3139
  if (cbk == null || rest.length > 0) return;
3147
3140
  const checkForUsageInsideUseEffectReport = checkForUsageInsideUseEffect$1(context.sourceCode, init);
3148
- const scope = context.sourceCode.getScope(init);
3141
+ context.sourceCode.getScope(init);
3149
3142
  const component = context.sourceCode.getScope(init).block;
3150
3143
  if (!ast.isFunction(component)) return;
3151
3144
  const [arg0, arg1] = init.arguments;
3152
3145
  if (arg0 == null || arg1 == null) return;
3153
3146
  if (!match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
3154
- const initNode = resolve$3(findVariable(scope, n.name));
3147
+ const initNode = resolve(context, n);
3155
3148
  if (initNode?.type !== AST_NODE_TYPES.ArrayExpression) return false;
3156
3149
  return initNode.elements.length === 0;
3157
3150
  }).otherwise(() => false)) {
@@ -3162,7 +3155,7 @@ function create$22(context) {
3162
3155
  if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) return n.body;
3163
3156
  return n;
3164
3157
  }).with({ type: AST_NODE_TYPES.FunctionExpression }, identity).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
3165
- const initNode = resolve$3(findVariable(scope, n.name));
3158
+ const initNode = resolve(context, n);
3166
3159
  if (initNode?.type !== AST_NODE_TYPES.ArrowFunctionExpression && initNode?.type !== AST_NODE_TYPES.FunctionExpression) return null;
3167
3160
  return initNode;
3168
3161
  }).otherwise(() => null);
@@ -3181,17 +3174,17 @@ function create$22(context) {
3181
3174
  } });
3182
3175
  }
3183
3176
  function checkForUsageInsideUseEffect$1(sourceCode, node) {
3184
- if (!/use\w*Effect/u.test(sourceCode.text)) return;
3185
- if (!isVariableDeclarator(node.parent)) return;
3186
- if (!isIdentifier(node.parent.id)) return;
3177
+ if (!/use\w*Effect/u.test(sourceCode.text)) return null;
3178
+ if (!isVariableDeclarator(node.parent)) return null;
3179
+ if (!isIdentifier(node.parent.id)) return null;
3187
3180
  const usages = (sourceCode.getDeclaredVariables(node.parent)[0]?.references ?? []).filter((ref) => ref.init !== true);
3188
- if (usages.length === 0) return;
3181
+ if (usages.length === 0) return null;
3189
3182
  const effectSet = /* @__PURE__ */ new Set();
3190
3183
  for (const usage of usages) {
3191
3184
  const effect = ast.findParentNode(usage.identifier, core.isUseEffectLikeCall);
3192
- if (effect == null) return;
3185
+ if (effect == null) return null;
3193
3186
  effectSet.add(effect);
3194
- if (effectSet.size > 1) return;
3187
+ if (effectSet.size > 1) return null;
3195
3188
  }
3196
3189
  return {
3197
3190
  data: { name: node.parent.id.name },
@@ -3199,13 +3192,6 @@ function checkForUsageInsideUseEffect$1(sourceCode, node) {
3199
3192
  node
3200
3193
  };
3201
3194
  }
3202
- function resolve$3(v) {
3203
- if (v == null) return unit;
3204
- const def = v.defs.at(0);
3205
- if (def == null) return unit;
3206
- if ("init" in def.node && def.node.init != null && !("declarations" in def.node.init)) return def.node.init;
3207
- return def.node;
3208
- }
3209
3195
 
3210
3196
  //#endregion
3211
3197
  //#region src/rules/no-unnecessary-use-memo/no-unnecessary-use-memo.ts
@@ -3232,8 +3218,7 @@ function create$21(context) {
3232
3218
  const [mem, ...rest] = context.sourceCode.getDeclaredVariables(node);
3233
3219
  if (mem == null || rest.length > 0) return;
3234
3220
  const checkForUsageInsideUseEffectReport = checkForUsageInsideUseEffect(context.sourceCode, init);
3235
- const scope = context.sourceCode.getScope(init);
3236
- const component = scope.block;
3221
+ const component = context.sourceCode.getScope(init).block;
3237
3222
  if (!ast.isFunction(component)) return;
3238
3223
  const [arg0, arg1] = init.arguments;
3239
3224
  if (arg0 == null || arg1 == null) return;
@@ -3242,7 +3227,7 @@ function create$21(context) {
3242
3227
  return;
3243
3228
  }
3244
3229
  if (!match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
3245
- const initNode = resolve$2(findVariable(scope, n.name));
3230
+ const initNode = resolve(context, n);
3246
3231
  if (initNode?.type !== AST_NODE_TYPES.ArrayExpression) return false;
3247
3232
  return initNode.elements.length === 0;
3248
3233
  }).otherwise(() => false)) {
@@ -3253,9 +3238,9 @@ function create$21(context) {
3253
3238
  if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) return n.body;
3254
3239
  return n;
3255
3240
  }).with({ type: AST_NODE_TYPES.FunctionExpression }, identity).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
3256
- const variableNode = resolve$2(findVariable(scope, n.name));
3257
- if (variableNode?.type !== AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== AST_NODE_TYPES.FunctionExpression) return null;
3258
- return variableNode;
3241
+ const initNode = resolve(context, n);
3242
+ if (initNode?.type !== AST_NODE_TYPES.ArrowFunctionExpression && initNode?.type !== AST_NODE_TYPES.FunctionExpression) return null;
3243
+ return initNode;
3259
3244
  }).otherwise(() => null);
3260
3245
  if (arg0Node == null) return;
3261
3246
  function getChildScopes(scope) {
@@ -3272,17 +3257,17 @@ function create$21(context) {
3272
3257
  } });
3273
3258
  }
3274
3259
  function checkForUsageInsideUseEffect(sourceCode, node) {
3275
- if (!/use\w*Effect/u.test(sourceCode.text)) return;
3276
- if (!isVariableDeclarator(node.parent)) return;
3277
- if (!isIdentifier(node.parent.id)) return;
3260
+ if (!/use\w*Effect/u.test(sourceCode.text)) return null;
3261
+ if (!isVariableDeclarator(node.parent)) return null;
3262
+ if (!isIdentifier(node.parent.id)) return null;
3278
3263
  const usages = (sourceCode.getDeclaredVariables(node.parent)[0]?.references ?? []).filter((ref) => ref.init !== true);
3279
- if (usages.length === 0) return;
3264
+ if (usages.length === 0) return null;
3280
3265
  const effectSet = /* @__PURE__ */ new Set();
3281
3266
  for (const usage of usages) {
3282
3267
  const effect = ast.findParentNode(usage.identifier, core.isUseEffectLikeCall);
3283
- if (effect == null) return;
3268
+ if (effect == null) return null;
3284
3269
  effectSet.add(effect);
3285
- if (effectSet.size > 1) return;
3270
+ if (effectSet.size > 1) return null;
3286
3271
  }
3287
3272
  return {
3288
3273
  data: { name: node.parent.id.name },
@@ -3290,13 +3275,6 @@ function checkForUsageInsideUseEffect(sourceCode, node) {
3290
3275
  node
3291
3276
  };
3292
3277
  }
3293
- function resolve$2(v) {
3294
- if (v == null) return unit;
3295
- const def = v.defs.at(0);
3296
- if (def == null) return unit;
3297
- if ("init" in def.node && def.node.init != null && !("declarations" in def.node.init)) return def.node.init;
3298
- return def.node;
3299
- }
3300
3278
 
3301
3279
  //#endregion
3302
3280
  //#region src/rules/no-unnecessary-use-prefix/no-unnecessary-use-prefix.ts
@@ -3452,7 +3430,7 @@ function create$16(context) {
3452
3430
  const value = attribute.value;
3453
3431
  if (value?.type !== AST_NODE_TYPES.JSXExpressionContainer) return;
3454
3432
  const valueExpression = value.expression;
3455
- const construction = computeObjectType(valueExpression, context.sourceCode.getScope(valueExpression));
3433
+ const construction = computeObjectType(context, valueExpression);
3456
3434
  if (construction == null) return;
3457
3435
  if (core.isHookCall(construction.node)) return;
3458
3436
  getOrElseUpdate(constructions, functionEntry.node, () => []).push(construction);
@@ -3539,7 +3517,7 @@ function create$15(context, [options]) {
3539
3517
  if (prop.type !== AST_NODE_TYPES.Property || prop.value.type !== AST_NODE_TYPES.AssignmentPattern) continue;
3540
3518
  const { value } = prop;
3541
3519
  const { right } = value;
3542
- const construction = computeObjectType(value, context.sourceCode.getScope(value));
3520
+ const construction = computeObjectType(context, value);
3543
3521
  if (construction == null) continue;
3544
3522
  if (core.isHookCall(construction.node)) continue;
3545
3523
  if (safePatterns.length > 0) {
@@ -3831,7 +3809,7 @@ function create$12(context) {
3831
3809
  if (currentClass == null || !core.isClassComponent(currentClass)) return;
3832
3810
  if (node.static) {
3833
3811
  if (core.isGetDerivedStateFromProps(node) && isMatching({ params: [P.nonNullable, ...P.array()] })(node.value)) {
3834
- const defNode = stateDefs.get(currentClass)?.node;
3812
+ const defNode = stateDefs.get(currentClass)?.node ?? null;
3835
3813
  stateDefs.set(currentClass, {
3836
3814
  isUsed: true,
3837
3815
  node: defNode
@@ -3879,7 +3857,7 @@ function create$12(context) {
3879
3857
  if (currentMethod == null || currentMethod.static) return;
3880
3858
  if (currentMethod === constructorStack.at(-1)) return;
3881
3859
  if (!currentClass.body.body.includes(currentMethod)) return;
3882
- const defNode = stateDefs.get(currentClass)?.node;
3860
+ const defNode = stateDefs.get(currentClass)?.node ?? null;
3883
3861
  stateDefs.set(currentClass, {
3884
3862
  isUsed: true,
3885
3863
  node: defNode
@@ -3903,7 +3881,7 @@ function create$12(context) {
3903
3881
  if (prop.type === AST_NODE_TYPES.Property && isKeyLiteral(prop, prop.key)) return ast.getPropertyName(prop.key) === "state";
3904
3882
  return false;
3905
3883
  })) return;
3906
- const defNode = stateDefs.get(currentClass)?.node;
3884
+ const defNode = stateDefs.get(currentClass)?.node ?? null;
3907
3885
  stateDefs.set(currentClass, {
3908
3886
  isUsed: true,
3909
3887
  node: defNode
@@ -4016,7 +3994,7 @@ function create$10(context, [option]) {
4016
3994
  }
4017
3995
  const isChildElement = ast.isOneOf([AST_NODE_TYPES.JSXElement, AST_NODE_TYPES.JSXFragment])(node.parent);
4018
3996
  switch (true) {
4019
- case allowExpressions && !isChildElement && node.children.length === 1 && core.isJsxText(node.children.at(0)): return;
3997
+ case allowExpressions && !isChildElement && node.children.length === 1 && core.isJsxText(node.children.at(0) ?? null): return;
4020
3998
  case !allowExpressions && isChildElement:
4021
3999
  context.report({
4022
4000
  data: { reason: "contains less than two children" },
@@ -6566,7 +6544,7 @@ function create$5(context) {
6566
6544
  }
6567
6545
  }
6568
6546
  function isIdFromUseStateCall(id, at) {
6569
- const initNode = resolve$1(findVariable(context.sourceCode.getScope(id), id));
6547
+ const initNode = resolve(context, id);
6570
6548
  if (initNode == null) return false;
6571
6549
  if (initNode.type !== AST_NODE_TYPES.CallExpression) return false;
6572
6550
  if (!isUseStateCall(initNode)) return false;
@@ -6688,8 +6666,8 @@ function create$5(context) {
6688
6666
  }
6689
6667
  },
6690
6668
  "Program:exit"() {
6691
- const getSetStateCalls = (id, initialScope) => {
6692
- const node = resolve$1(findVariable(initialScope, id));
6669
+ const getSetStateCalls = (context, id) => {
6670
+ const node = resolve(context, id);
6693
6671
  switch (node?.type) {
6694
6672
  case AST_NODE_TYPES.ArrowFunctionExpression:
6695
6673
  case AST_NODE_TYPES.FunctionDeclaration:
@@ -6705,8 +6683,7 @@ function create$5(context) {
6705
6683
  });
6706
6684
  for (const { callee } of trackedFnCalls) {
6707
6685
  if (!("name" in callee)) continue;
6708
- const { name } = callee;
6709
- const setStateCalls = getSetStateCalls(name, context.sourceCode.getScope(callee));
6686
+ const setStateCalls = getSetStateCalls(context, callee);
6710
6687
  for (const setStateCall of setStateCalls) context.report({
6711
6688
  data: { name: getCallName(setStateCall) },
6712
6689
  messageId: "default",
@@ -6714,7 +6691,7 @@ function create$5(context) {
6714
6691
  });
6715
6692
  }
6716
6693
  for (const id of setupFnIds) {
6717
- const setStateCalls = getSetStateCalls(id.name, context.sourceCode.getScope(id));
6694
+ const setStateCalls = getSetStateCalls(context, id);
6718
6695
  for (const setStateCall of setStateCalls) context.report({
6719
6696
  data: { name: getCallName(setStateCall) },
6720
6697
  messageId: "default",
@@ -6724,17 +6701,6 @@ function create$5(context) {
6724
6701
  }
6725
6702
  });
6726
6703
  }
6727
- function resolve$1(v) {
6728
- if (v == null) return unit;
6729
- const def = v.defs.at(0);
6730
- if (def == null) return unit;
6731
- switch (true) {
6732
- case def.type === DefinitionType.FunctionName && def.node.type === AST_NODE_TYPES.FunctionDeclaration: return def.node;
6733
- case def.type === DefinitionType.ClassName && def.node.type === AST_NODE_TYPES.ClassDeclaration: return def.node;
6734
- case "init" in def.node && def.node.init != null && !("declarations" in def.node.init): return def.node.init;
6735
- default: return unit;
6736
- }
6737
- }
6738
6704
 
6739
6705
  //#endregion
6740
6706
  //#region src/rules/set-state-in-render/set-state-in-render.ts
@@ -6759,7 +6725,7 @@ function create$4(context) {
6759
6725
  return core.isUseStateLikeCall(node, additionalStateHooks);
6760
6726
  }
6761
6727
  function isIdFromUseStateCall(topLevelId, at) {
6762
- const initNode = resolve(findVariable(context.sourceCode.getScope(topLevelId), topLevelId));
6728
+ const initNode = resolve(context, topLevelId);
6763
6729
  if (initNode == null) return false;
6764
6730
  if (initNode.type !== AST_NODE_TYPES.CallExpression) return false;
6765
6731
  if (!isUseStateCall(initNode)) return false;
@@ -6872,13 +6838,6 @@ function create$4(context) {
6872
6838
  }
6873
6839
  });
6874
6840
  }
6875
- function resolve(v) {
6876
- if (v == null) return unit;
6877
- const def = v.defs.at(0);
6878
- if (def == null) return unit;
6879
- if ("init" in def.node && def.node.init != null && !("declarations" in def.node.init)) return def.node.init;
6880
- return def.node;
6881
- }
6882
6841
 
6883
6842
  //#endregion
6884
6843
  //#region src/rules/unsupported-syntax/unsupported-syntax.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-x",
3
- "version": "3.0.0-beta.63",
3
+ "version": "3.0.0-beta.64",
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",
@@ -45,18 +45,18 @@
45
45
  "string-ts": "^2.3.1",
46
46
  "ts-api-utils": "^2.4.0",
47
47
  "ts-pattern": "^5.9.0",
48
- "@eslint-react/ast": "3.0.0-beta.63",
49
- "@eslint-react/eff": "3.0.0-beta.63",
50
- "@eslint-react/core": "3.0.0-beta.63",
51
- "@eslint-react/shared": "3.0.0-beta.63",
52
- "@eslint-react/var": "3.0.0-beta.63"
48
+ "@eslint-react/ast": "3.0.0-beta.64",
49
+ "@eslint-react/eff": "3.0.0-beta.64",
50
+ "@eslint-react/core": "3.0.0-beta.64",
51
+ "@eslint-react/shared": "3.0.0-beta.64",
52
+ "@eslint-react/var": "3.0.0-beta.64"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@types/react": "^19.2.14",
56
56
  "@types/react-dom": "^19.2.3",
57
57
  "eslint": "^10.0.2",
58
58
  "tsdown": "^0.21.0-beta.2",
59
- "tsl-dx": "^0.8.0",
59
+ "tsl-dx": "^0.9.0",
60
60
  "@local/configs": "0.0.0"
61
61
  },
62
62
  "peerDependencies": {