eslint-plugin-react-x 2.6.1 → 2.6.2-beta.0

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 +31 -18
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { AST_NODE_TYPES } from "@typescript-eslint/types";
3
3
  import { ESLintUtils } from "@typescript-eslint/utils";
4
4
  import { P, isMatching, match } from "ts-pattern";
5
5
  import ts from "typescript";
6
- import { ComponentDetectionHint, ComponentFlag, DEFAULT_COMPONENT_DETECTION_HINT, JsxEmit, findEnclosingAssignmentTarget, findParentJsxAttribute, getJsxAttribute, getJsxAttributeName, getJsxConfigFromAnnotation, getJsxConfigFromContext, getJsxElementType, isAssignmentToThisState, isCaptureOwnerStackCall, isChildrenCount, isChildrenForEach, isChildrenMap, isChildrenOnly, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUpdate, isCreateContextCall, isCreateElementCall, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRefCall, isGetDerivedStateFromError, isGetDerivedStateFromProps, isInitializedFromReact, isInstanceIdEqual, isJsxFragmentElement, isJsxHostElement, isJsxText, isLazyCall, isReactHookCall, isReactHookName, isRenderMethodLike, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseCall, isUseCallbackCall, isUseContextCall, isUseEffectLikeCall, isUseMemoCall, isUseRefCall, isUseStateCall, useComponentCollector, useComponentCollectorLegacy, useHookCollector } from "@eslint-react/core";
6
+ import { ComponentDetectionHint, ComponentFlag, DEFAULT_COMPONENT_DETECTION_HINT, JsxEmit, findEnclosingAssignmentTarget, findParentJsxAttribute, getJsxAttribute, getJsxAttributeName, getJsxConfigFromAnnotation, getJsxConfigFromContext, getJsxElementType, isAssignmentToThisState, isCaptureOwnerStackCall, isChildrenCount, isChildrenForEach, isChildrenMap, isChildrenOnly, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUpdate, isCreateContextCall, isCreateElementCall, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRefCall, isGetDerivedStateFromError, isGetDerivedStateFromProps, isInitializedFromReact, isInstanceIdEqual, isJsxFragmentElement, isJsxHostElement, isJsxText, isLazyCall, isReactHookCall, isReactHookName, isRenderFunctionLoose, isRenderMethodLike, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseCall, isUseCallbackCall, isUseContextCall, isUseEffectLikeCall, isUseMemoCall, isUseRefCall, isUseStateCall, useComponentCollector, useComponentCollectorLegacy, useHookCollector } from "@eslint-react/core";
7
7
  import * as AST from "@eslint-react/ast";
8
8
  import { findVariable, getChildScopes, getObjectType, getVariableDefinitionNode } from "@eslint-react/var";
9
9
  import { constFalse, constTrue, flow, getOrElseUpdate, identity, unit } from "@eslint-react/eff";
@@ -34,7 +34,7 @@ var __exportAll = (all, symbols) => {
34
34
  //#endregion
35
35
  //#region package.json
36
36
  var name$6 = "eslint-plugin-react-x";
37
- var version = "2.6.1";
37
+ var version = "2.6.2-beta.0";
38
38
 
39
39
  //#endregion
40
40
  //#region src/utils/create-rule.ts
@@ -577,7 +577,7 @@ function create$53(context) {
577
577
  classStack.pop();
578
578
  },
579
579
  MemberExpression(node) {
580
- if (!AST.isThisExpression(node.object)) return;
580
+ if (!AST.isThisExpressionLoose(node.object)) return;
581
581
  const [currClass, isComponent = false] = classStack.at(-1) ?? [];
582
582
  if (currClass == null || !isComponent) return;
583
583
  const [currMethod, isStatic = false] = methodStack.at(-1) ?? [];
@@ -609,7 +609,7 @@ function create$53(context) {
609
609
  if (currMethod == null || isStatic) return;
610
610
  const [setState, hasThisState = false] = setStateStack.at(-1) ?? [];
611
611
  if (setState == null || hasThisState) return;
612
- if (node.init == null || !AST.isThisExpression(node.init) || node.id.type !== AST_NODE_TYPES.ObjectPattern) return;
612
+ if (node.init == null || !AST.isThisExpressionLoose(node.init) || node.id.type !== AST_NODE_TYPES.ObjectPattern) return;
613
613
  if (!node.id.properties.some((prop) => prop.type === AST_NODE_TYPES.Property && isKeyLiteral$2(prop, prop.key) && AST.getPropertyName(prop.key) === "state")) return;
614
614
  context.report({
615
615
  messageId: "noAccessStateInSetstate",
@@ -623,6 +623,23 @@ function create$53(context) {
623
623
  //#region src/rules/no-array-index-key.ts
624
624
  const RULE_NAME$52 = "no-array-index-key";
625
625
  const REACT_CHILDREN_METHOD = ["forEach", "map"];
626
+ const arrayIndexParamPosition = new Map([
627
+ ["every", 1],
628
+ ["filter", 1],
629
+ ["find", 1],
630
+ ["findIndex", 1],
631
+ ["findLast", 1],
632
+ ["findLastIndex", 1],
633
+ ["flatMap", 1],
634
+ ["forEach", 1],
635
+ ["map", 1],
636
+ ["reduce", 2],
637
+ ["reduceRight", 2],
638
+ ["some", 1]
639
+ ]);
640
+ function getArrayIndexParamPosition(methodName) {
641
+ return arrayIndexParamPosition.get(methodName) ?? -1;
642
+ }
626
643
  function isReactChildrenMethod(name$7) {
627
644
  return REACT_CHILDREN_METHOD.includes(name$7);
628
645
  }
@@ -641,7 +658,7 @@ function getMapIndexParamName(context, node) {
641
658
  if (callee.type !== AST_NODE_TYPES.MemberExpression) return unit;
642
659
  if (callee.property.type !== AST_NODE_TYPES.Identifier) return unit;
643
660
  const { name: name$7 } = callee.property;
644
- const indexPosition = AST.getArrayMethodCallbackIndexParamPosition(name$7);
661
+ const indexPosition = getArrayIndexParamPosition(name$7);
645
662
  if (indexPosition === -1) return unit;
646
663
  const callbackArg = node.arguments[isUsingReactChildren(context, node) ? 1 : 0];
647
664
  if (callbackArg == null) return unit;
@@ -2079,7 +2096,8 @@ function create$20(context) {
2079
2096
  const jsxElement = node.parent.parent;
2080
2097
  if (isJsxFragmentElement(context, jsxElement, jsxConfig)) return;
2081
2098
  if (jsxElement.openingElement.attributes.some((attr) => attr.type === AST_NODE_TYPES.JSXSpreadAttribute)) return;
2082
- const mapCallback = AST.findParentNode(jsxElement, isMapCallback);
2099
+ if (AST.findParentNode(jsxElement, (n) => isRenderFunctionLoose(context, n)) != null) return;
2100
+ const mapCallback = AST.findParentNode(jsxElement, isArrayMethodCallback);
2083
2101
  if (mapCallback == null || AST.findParentNode(jsxElement, AST.isFunction) !== mapCallback) {
2084
2102
  if (!(AST.findParentNode(jsxElement, (n) => AST.isConditional(n) || AST.isControlFlow(n) || findEnclosingAssignmentTarget(n) != null) != null)) context.report({
2085
2103
  messageId: "noUnnecessaryKey",
@@ -2101,14 +2119,9 @@ function create$20(context) {
2101
2119
  });
2102
2120
  } };
2103
2121
  }
2104
- /**
2105
- * Checks if a node is a callback function passed to an array's `.map()` method
2106
- * @param node The node to check
2107
- * @returns `true` if the node is a map callback, `false` otherwise
2108
- */
2109
- function isMapCallback(node) {
2110
- if (node.parent == null) return false;
2111
- if (!AST.isArrayMapCall(node.parent)) return false;
2122
+ function isArrayMethodCallback(node) {
2123
+ if (node.parent?.type !== AST_NODE_TYPES.CallExpression) return false;
2124
+ if (!AST.isArrayMapCall(node.parent) && !AST.isArrayFromCall(node.parent)) return false;
2112
2125
  return AST.isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(AST.getUnderlyingExpression(node));
2113
2126
  }
2114
2127
 
@@ -2653,7 +2666,7 @@ function create$10(context) {
2653
2666
  const currentMethod = methodStack.at(-1);
2654
2667
  if (currentClass == null || currentMethod == null) return;
2655
2668
  if (!isClassComponent(currentClass) || currentMethod.static) return;
2656
- if (!AST.isThisExpression(node.object) || !isKeyLiteral$1(node, node.property)) return;
2669
+ if (!AST.isThisExpressionLoose(node.object) || !isKeyLiteral$1(node, node.property)) return;
2657
2670
  if (node.parent.type === AST_NODE_TYPES.AssignmentExpression && node.parent.left === node) {
2658
2671
  propertyDefs.get(currentClass)?.add(node.property);
2659
2672
  return;
@@ -2670,7 +2683,7 @@ function create$10(context) {
2670
2683
  const currentMethod = methodStack.at(-1);
2671
2684
  if (currentClass == null || currentMethod == null) return;
2672
2685
  if (!isClassComponent(currentClass) || currentMethod.static) return;
2673
- if (node.init != null && AST.isThisExpression(node.init) && node.id.type === AST_NODE_TYPES.ObjectPattern) {
2686
+ if (node.init != null && AST.isThisExpressionLoose(node.init) && node.id.type === AST_NODE_TYPES.ObjectPattern) {
2674
2687
  for (const prop of node.id.properties) if (prop.type === AST_NODE_TYPES.Property && isKeyLiteral$1(prop, prop.key)) {
2675
2688
  const keyName = AST.getPropertyName(prop.key);
2676
2689
  if (keyName != null) propertyUsages.get(currentClass)?.add(keyName);
@@ -2879,7 +2892,7 @@ function create$8(context) {
2879
2892
  ClassExpression: classEnter,
2880
2893
  "ClassExpression:exit": classExit,
2881
2894
  MemberExpression(node) {
2882
- if (!AST.isThisExpression(node.object)) return;
2895
+ if (!AST.isThisExpressionLoose(node.object)) return;
2883
2896
  if (AST.getPropertyName(node.property) !== "state") return;
2884
2897
  const currentClass = classStack.at(-1);
2885
2898
  if (currentClass == null || !isClassComponent(currentClass)) return;
@@ -2906,7 +2919,7 @@ function create$8(context) {
2906
2919
  if (currentMethod == null || currentMethod.static) return;
2907
2920
  if (currentMethod === constructorStack.at(-1)) return;
2908
2921
  if (!currentClass.body.body.includes(currentMethod)) return;
2909
- if (node.init == null || !AST.isThisExpression(node.init) || node.id.type !== AST_NODE_TYPES.ObjectPattern) return;
2922
+ if (node.init == null || !AST.isThisExpressionLoose(node.init) || node.id.type !== AST_NODE_TYPES.ObjectPattern) return;
2910
2923
  if (!node.id.properties.some((prop) => {
2911
2924
  if (prop.type === AST_NODE_TYPES.Property && isKeyLiteral(prop, prop.key)) return AST.getPropertyName(prop.key) === "state";
2912
2925
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-x",
3
- "version": "2.6.1",
3
+ "version": "2.6.2-beta.0",
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",
@@ -46,11 +46,11 @@
46
46
  "string-ts": "^2.3.1",
47
47
  "ts-api-utils": "^2.4.0",
48
48
  "ts-pattern": "^5.9.0",
49
- "@eslint-react/ast": "2.6.1",
50
- "@eslint-react/core": "2.6.1",
51
- "@eslint-react/eff": "2.6.1",
52
- "@eslint-react/var": "2.6.1",
53
- "@eslint-react/shared": "2.6.1"
49
+ "@eslint-react/ast": "2.6.2-beta.0",
50
+ "@eslint-react/core": "2.6.2-beta.0",
51
+ "@eslint-react/eff": "2.6.2-beta.0",
52
+ "@eslint-react/shared": "2.6.2-beta.0",
53
+ "@eslint-react/var": "2.6.2-beta.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@types/react": "^19.2.8",