eslint-plugin-react-x 2.0.0-beta.174 → 2.0.0-beta.176

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 +42 -70
  2. package/package.json +11 -11
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-beta.174";
118
+ var version = "2.0.0-beta.176";
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 jsxConfig = {
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
- const hasAttributes = node.openingElement.attributes.length > 0;
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 jsxConfig = {
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
- const hasState = node.id.properties.some((prop) => prop.type === AST_NODE_TYPES.Property && isKeyLiteral$2(prop, prop.key) && AST.getPropertyName(prop.key) === "state");
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 getAttribute = ER.getAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node));
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 fullName = ER.getElementType(context, node);
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
- const forbiddenPropRegExp = RegExp.toRegExp(forbiddenProp);
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
- const isLeftUnaryNot = left.type === AST_NODE_TYPES.UnaryExpression && left.operator === "!";
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
- const isLeftNan = left.type === AST_NODE_TYPES.Identifier && left.name === "NaN" || getStaticValue(left, initialScope)?.value === "NaN";
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
- const isLeftValid = Array.from(leftTypeVariants.values()).every((type) => allowedVariants.some((allowed) => allowed === type));
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 variable = VAR.findVariable(n.name, context.sourceCode.getScope(n));
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
- const hasDisplayNameAssignment = displayNameAssignments.some((node) => {
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
- const significantParent = AST.findParentNode(lazy, (n) => {
1988
- if (AST.isJSX(n)) return true;
1989
- if (n.type === AST_NODE_TYPES.CallExpression) return ER.isReactHookCall(n) || ER.isCreateElementCall(context, n) || ER.isCreateContextCall(context, n);
1990
- if (AST.isFunction(n)) return functionComponents.some((c) => c.node === n);
1991
- if (AST.isClass(n)) return classComponents.some((c) => c.node === n);
1992
- return false;
1993
- });
1994
- if (significantParent != null) context.report({
1995
- messageId: "noNestedLazyComponentDeclarations",
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
  }
@@ -2263,12 +2248,13 @@ var no_unnecessary_key_default = createRule({
2263
2248
  defaultOptions: []
2264
2249
  });
2265
2250
  function create$18(context) {
2266
- if (!context.sourceCode.getText().includes("key=")) return {};
2251
+ if (!context.sourceCode.text.includes("key=")) return {};
2267
2252
  return { JSXAttribute(node) {
2268
2253
  if (node.name.name !== "key") return;
2269
2254
  const jsxElement = node.parent.parent;
2255
+ const initialScope = context.sourceCode.getScope(jsxElement);
2270
2256
  const pMapCallback = AST.findParentNode(jsxElement, isMapCallback);
2271
- if (pMapCallback == null) return;
2257
+ if (pMapCallback == null || context.sourceCode.getScope(pMapCallback) !== initialScope) return;
2272
2258
  const pKeyedElementOrElse = AST.findParentNode(jsxElement, (n) => {
2273
2259
  if (n === pMapCallback) return true;
2274
2260
  return AST.isJSXElement(n) && n.openingElement.attributes.some((n$1) => n$1.type === AST_NODE_TYPES.JSXAttribute && n$1.name.type === AST_NODE_TYPES.JSXIdentifier && n$1.name.name === "key");
@@ -2313,13 +2299,12 @@ function create$17(context) {
2313
2299
  if (!AST.isFunction(component)) return;
2314
2300
  const [arg0, arg1] = node.arguments;
2315
2301
  if (arg0 == null || arg1 == null) return;
2316
- const hasEmptyDeps = match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
2302
+ if (!match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
2317
2303
  const variable = VAR.findVariable(n.name, initialScope);
2318
2304
  const variableNode = VAR.getVariableDefinitionNode(variable, 0);
2319
2305
  if (variableNode?.type !== AST_NODE_TYPES.ArrayExpression) return false;
2320
2306
  return variableNode.elements.length === 0;
2321
- }).otherwise(() => false);
2322
- if (!hasEmptyDeps) return;
2307
+ }).otherwise(() => false)) return;
2323
2308
  const arg0Node = match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
2324
2309
  if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) return n.body;
2325
2310
  return n;
@@ -2331,9 +2316,7 @@ function create$17(context) {
2331
2316
  }).otherwise(() => null);
2332
2317
  if (arg0Node == null) return;
2333
2318
  const arg0NodeScope = context.sourceCode.getScope(arg0Node);
2334
- const arg0NodeReferences = VAR.getChildScopes(arg0NodeScope).flatMap((x) => x.references);
2335
- const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
2336
- if (!isReferencedToComponentScope) context.report({
2319
+ if (!VAR.getChildScopes(arg0NodeScope).flatMap((x) => x.references).some((x) => x.resolved?.scope.block === component)) context.report({
2337
2320
  messageId: "noUnnecessaryUseCallback",
2338
2321
  node
2339
2322
  });
@@ -2363,20 +2346,17 @@ function create$16(context) {
2363
2346
  return { CallExpression(node) {
2364
2347
  const initialScope = context.sourceCode.getScope(node);
2365
2348
  if (!ER.isUseMemoCall(node)) return;
2366
- const scope = context.sourceCode.getScope(node);
2367
- const component = scope.block;
2349
+ const component = context.sourceCode.getScope(node).block;
2368
2350
  if (!AST.isFunction(component)) return;
2369
2351
  const [arg0, arg1] = node.arguments;
2370
2352
  if (arg0 == null || arg1 == null) return;
2371
- const hasCallInArg0 = AST.isFunction(arg0) && [...AST.getNestedCallExpressions(arg0.body), ...AST.getNestedNewExpressions(arg0.body)].length > 0;
2372
- if (hasCallInArg0) return;
2373
- 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) => {
2374
2355
  const variable = VAR.findVariable(n.name, initialScope);
2375
2356
  const variableNode = VAR.getVariableDefinitionNode(variable, 0);
2376
2357
  if (variableNode?.type !== AST_NODE_TYPES.ArrayExpression) return false;
2377
2358
  return variableNode.elements.length === 0;
2378
- }).otherwise(() => false);
2379
- if (!hasEmptyDeps) return;
2359
+ }).otherwise(() => false)) return;
2380
2360
  const arg0Node = match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
2381
2361
  if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) return n.body;
2382
2362
  return n;
@@ -2388,9 +2368,7 @@ function create$16(context) {
2388
2368
  }).otherwise(() => null);
2389
2369
  if (arg0Node == null) return;
2390
2370
  const arg0NodeScope = context.sourceCode.getScope(arg0Node);
2391
- const arg0NodeReferences = VAR.getChildScopes(arg0NodeScope).flatMap((x) => x.references);
2392
- const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
2393
- if (!isReferencedToComponentScope) context.report({
2371
+ if (!VAR.getChildScopes(arg0NodeScope).flatMap((x) => x.references).some((x) => x.resolved?.scope.block === component)) context.report({
2394
2372
  messageId: "noUnnecessaryUseMemo",
2395
2373
  node
2396
2374
  });
@@ -2575,8 +2553,7 @@ function create$11(context) {
2575
2553
  return {
2576
2554
  ...listeners,
2577
2555
  JSXOpeningElement(node) {
2578
- const fullName = ER.getElementType(context, node.parent);
2579
- const selfName = fullName.split(".").at(-1);
2556
+ const selfName = ER.getElementType(context, node.parent).split(".").at(-1);
2580
2557
  if (selfName == null) return;
2581
2558
  if (!isContextName(selfName, isReact18OrBelow)) return;
2582
2559
  const functionEntry = ctx.getCurrentEntry();
@@ -2824,8 +2801,7 @@ function create$8(context) {
2824
2801
  const [props] = component.node.params;
2825
2802
  if (props == null) continue;
2826
2803
  const usedPropKeys = /* @__PURE__ */ new Set();
2827
- const couldFindAllUsedPropKeys = collectUsedPropKeysOfParameter(context, usedPropKeys, props);
2828
- if (!couldFindAllUsedPropKeys) continue;
2804
+ if (!collectUsedPropKeysOfParameter(context, usedPropKeys, props)) continue;
2829
2805
  const tsNode = services.esTreeNodeToTSNodeMap.get(props);
2830
2806
  const declaredProps = checker.getTypeAtLocation(tsNode).getProperties();
2831
2807
  for (const declaredProp of declaredProps) {
@@ -2866,8 +2842,7 @@ function collectUsedPropsOfRestElement(context, usedPropKeys, restElement) {
2866
2842
  }
2867
2843
  }
2868
2844
  function collectUsedPropKeysOfIdentifier(context, usedPropKeys, identifier) {
2869
- const scope = context.sourceCode.getScope(identifier);
2870
- const variable = scope.variables.find((v) => v.name === identifier.name);
2845
+ const variable = context.sourceCode.getScope(identifier).variables.find((v) => v.name === identifier.name);
2871
2846
  if (variable == null) return false;
2872
2847
  for (const ref of variable.references) {
2873
2848
  if (ref.identifier === identifier) continue;
@@ -3030,11 +3005,10 @@ function create$7(context) {
3030
3005
  if (currentMethod === constructorEntries.at(-1)) return;
3031
3006
  if (!currentClass.body.body.includes(currentMethod)) return;
3032
3007
  if (node.init == null || !AST.isThisExpression(node.init) || node.id.type !== AST_NODE_TYPES.ObjectPattern) return;
3033
- const hasState = node.id.properties.some((prop) => {
3008
+ if (!node.id.properties.some((prop) => {
3034
3009
  if (prop.type === AST_NODE_TYPES.Property && isKeyLiteral(prop, prop.key)) return AST.getPropertyName(prop.key) === "state";
3035
3010
  return false;
3036
- });
3037
- if (!hasState) return;
3011
+ })) return;
3038
3012
  const defNode = stateDefs.get(currentClass)?.node;
3039
3013
  stateDefs.set(currentClass, {
3040
3014
  node: defNode,
@@ -3149,8 +3123,7 @@ function create$5(context) {
3149
3123
  if (!ER.isForwardRefCall(context, node)) return;
3150
3124
  const [component] = node.arguments;
3151
3125
  if (component == null || !AST.isFunction(component)) return;
3152
- const ref = component.params[1];
3153
- if (ref != null) return;
3126
+ if (component.params[1] != null) return;
3154
3127
  context.report({
3155
3128
  messageId: "noUselessForwardRef",
3156
3129
  node: node.callee
@@ -3384,8 +3357,7 @@ function create$2(context) {
3384
3357
  const importDeclarationText = context.sourceCode.getText(node.parent);
3385
3358
  const semi = importDeclarationText.endsWith(";") ? ";" : "";
3386
3359
  const quote = node.parent.source.raw.at(0) ?? "'";
3387
- const isTypeImport = node.parent.importKind === "type";
3388
- const importStringPrefix = `import${isTypeImport ? " type" : ""}`;
3360
+ const importStringPrefix = `import${node.parent.importKind === "type" ? " type" : ""}`;
3389
3361
  const importSourceQuoted = `${quote}${importSource}${quote}`;
3390
3362
  if (!hasOtherSpecifiers) return fixer.replaceText(node.parent, `${importStringPrefix} * as ${node.local.name} from ${importSourceQuoted}${semi}`);
3391
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-beta.174",
3
+ "version": "2.0.0-beta.176",
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,20 +34,20 @@
34
34
  "./package.json"
35
35
  ],
36
36
  "dependencies": {
37
- "@typescript-eslint/scope-manager": "^8.42.0",
38
- "@typescript-eslint/type-utils": "^8.42.0",
39
- "@typescript-eslint/types": "^8.42.0",
40
- "@typescript-eslint/utils": "^8.42.0",
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-beta.174",
46
- "@eslint-react/core": "2.0.0-beta.174",
47
- "@eslint-react/eff": "2.0.0-beta.174",
48
- "@eslint-react/kit": "2.0.0-beta.174",
49
- "@eslint-react/shared": "2.0.0-beta.174",
50
- "@eslint-react/var": "2.0.0-beta.174"
45
+ "@eslint-react/ast": "2.0.0-beta.176",
46
+ "@eslint-react/core": "2.0.0-beta.176",
47
+ "@eslint-react/kit": "2.0.0-beta.176",
48
+ "@eslint-react/eff": "2.0.0-beta.176",
49
+ "@eslint-react/var": "2.0.0-beta.176",
50
+ "@eslint-react/shared": "2.0.0-beta.176"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/react": "^19.1.12",