eslint-plugin-react-x 1.22.2-next.9 → 1.23.0-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.
package/dist/index.js CHANGED
@@ -42,7 +42,7 @@ var ts__default = /*#__PURE__*/_interopDefault(ts);
42
42
 
43
43
  // package.json
44
44
  var name = "eslint-plugin-react-x";
45
- var version = "1.22.2-next.9";
45
+ var version = "1.23.0-beta.0";
46
46
  var createRule = shared.createRuleForPlugin("x");
47
47
 
48
48
  // src/rules/avoid-shorthand-boolean.ts
@@ -327,12 +327,10 @@ var no_array_index_key_default = createRule({
327
327
  name: RULE_NAME5,
328
328
  create(context) {
329
329
  const indexParamNames = [];
330
+ const isCreateOrCloneElementCall = eff.or(core.isCreateElementCall(context), core.isCloneElementCall(context));
330
331
  function isArrayIndex(node) {
331
332
  return node.type === types.AST_NODE_TYPES.Identifier && indexParamNames.some(eff.O.exists((name2) => name2 === node.name));
332
333
  }
333
- function isCreateOrCloneElementCall(node) {
334
- return core.isCreateElementCall(node, context) || core.isCloneElementCall(node, context);
335
- }
336
334
  function getReportDescriptor(node) {
337
335
  if (isArrayIndex(node)) return [{ messageId: "noArrayIndexKey", node }];
338
336
  if (AST11__namespace.isOneOf([types.AST_NODE_TYPES.TemplateLiteral, types.AST_NODE_TYPES.BinaryExpression])(node)) {
@@ -1862,9 +1860,15 @@ var no_set_state_in_component_did_mount_default = createRule({
1862
1860
  eff.O.Do,
1863
1861
  eff.O.bind("clazz", () => AST11__namespace.traverseUpGuard(node, core.isClassComponent)),
1864
1862
  eff.O.bind("method", ({ clazz }) => AST11__namespace.traverseUpStop(node, clazz, isComponentDidMount)),
1863
+ eff.O.bind("methodScope", ({ method }) => eff.O.some(context.sourceCode.getScope(method))),
1865
1864
  eff.O.bind("upperScope", () => eff.O.fromNullable(context.sourceCode.getScope(node).upper)),
1866
1865
  eff.O.filter(
1867
- ({ clazz, method, upperScope }) => method.parent === clazz.body && upperScope === context.sourceCode.getScope(method)
1866
+ ({
1867
+ clazz,
1868
+ method,
1869
+ methodScope,
1870
+ upperScope
1871
+ }) => method.parent === clazz.body && upperScope === methodScope
1868
1872
  ),
1869
1873
  eff.O.map(() => ({
1870
1874
  messageId: "noSetStateInComponentDidMount",
@@ -2156,39 +2160,40 @@ var no_unstable_context_value_default = createRule({
2156
2160
  name: RULE_NAME40,
2157
2161
  create(context) {
2158
2162
  const { ctx, listeners } = core.useComponentCollector(context);
2159
- const possibleValueConstructions = /* @__PURE__ */ new Map();
2163
+ const constructions = /* @__PURE__ */ new Map();
2160
2164
  return {
2161
2165
  ...listeners,
2162
2166
  JSXOpeningElement(node) {
2163
2167
  const openingElementName = node.name;
2164
2168
  if (openingElementName.type !== types.AST_NODE_TYPES.JSXMemberExpression) return;
2165
2169
  if (openingElementName.property.name !== "Provider") return;
2166
- const maybeJSXValueAttribute = eff.O.fromNullable(
2167
- node.attributes.find((attribute) => {
2168
- return attribute.type === types.AST_NODE_TYPES.JSXAttribute && attribute.name.name === "value";
2169
- })
2170
+ const constructionEntry = eff.F.pipe(
2171
+ eff.O.Do,
2172
+ eff.O.bind("function", ctx.getCurrentFunction),
2173
+ eff.O.bind("attribute", () => eff.O.fromNullable(
2174
+ node.attributes.find((attribute) => {
2175
+ return attribute.type === types.AST_NODE_TYPES.JSXAttribute && attribute.name.name === "value";
2176
+ })
2177
+ )),
2178
+ eff.O.bind("value", ({ attribute }) => "value" in attribute ? eff.O.some(attribute.value) : eff.O.none()),
2179
+ eff.O.bind("valueExpression", ({ value }) => value?.type === types.AST_NODE_TYPES.JSXExpressionContainer ? eff.O.some(value.expression) : eff.O.none()),
2180
+ eff.O.bind("construction", ({ valueExpression }) => {
2181
+ const initialScope = context.sourceCode.getScope(valueExpression);
2182
+ return eff.O.some(VAR__namespace.inspectConstruction(valueExpression, initialScope));
2183
+ }),
2184
+ eff.O.filter(({ construction }) => construction._tag !== "None")
2170
2185
  );
2171
- if (eff.O.isNone(maybeJSXValueAttribute) || !("value" in maybeJSXValueAttribute.value)) return;
2172
- const valueNode = maybeJSXValueAttribute.value.value;
2173
- if (valueNode?.type !== types.AST_NODE_TYPES.JSXExpressionContainer) return;
2174
- const valueExpression = valueNode.expression;
2175
- const initialScope = context.sourceCode.getScope(valueExpression);
2176
- const construction = VAR__namespace.inspectConstruction(valueExpression, initialScope);
2177
- if (construction._tag === "None") return;
2178
- eff.O.map(
2179
- ctx.getCurrentFunction(),
2180
- ([_, currentFn]) => possibleValueConstructions.set(currentFn, [
2181
- ...possibleValueConstructions.get(currentFn) ?? [],
2186
+ for (const { construction, function: [_, fNode] } of eff.O.toArray(constructionEntry)) {
2187
+ constructions.set(fNode, [
2188
+ ...constructions.get(fNode) ?? [],
2182
2189
  construction
2183
- ])
2184
- );
2190
+ ]);
2191
+ }
2185
2192
  },
2186
2193
  "Program:exit"(node) {
2187
2194
  const components = ctx.getAllComponents(node).values();
2188
2195
  for (const { node: component } of components) {
2189
- const constructions = possibleValueConstructions.get(component);
2190
- if (!constructions) continue;
2191
- for (const construction of constructions) {
2196
+ for (const construction of constructions.get(component) ?? []) {
2192
2197
  if (construction._tag === "None") continue;
2193
2198
  const { node: constructionNode, _tag } = construction;
2194
2199
  const messageId = _tag.startsWith("Function") ? "noUnstableContextValueWithFunction" : "noUnstableContextValueWithIdentifier";
@@ -2225,7 +2230,7 @@ var no_unstable_default_props_default = createRule({
2225
2230
  name: RULE_NAME41,
2226
2231
  create(context) {
2227
2232
  const { ctx, listeners } = core.useComponentCollector(context);
2228
- const possibleDestructuringDeclarators = /* @__PURE__ */ new WeakMap();
2233
+ const declarators = /* @__PURE__ */ new WeakMap();
2229
2234
  return {
2230
2235
  ...listeners,
2231
2236
  "Program:exit"(node) {
@@ -2235,10 +2240,7 @@ var no_unstable_default_props_default = createRule({
2235
2240
  const [props] = params;
2236
2241
  if (!props) continue;
2237
2242
  const properties = tsPattern.match(props).with({ type: types.AST_NODE_TYPES.ObjectPattern }, ({ properties: properties2 }) => properties2).with({ type: types.AST_NODE_TYPES.Identifier }, ({ name: name2 }) => {
2238
- const variableDeclarators = possibleDestructuringDeclarators.get(component);
2239
- if (!variableDeclarators) return [];
2240
- const declarators = variableDeclarators.filter((d) => d.init.name === name2);
2241
- return declarators.flatMap((d) => d.id.properties);
2243
+ return declarators.get(component)?.filter((d) => d.init.name === name2).flatMap((d) => d.id.properties) ?? [];
2242
2244
  }).otherwise(() => []);
2243
2245
  for (const prop of properties) {
2244
2246
  if (prop.type !== types.AST_NODE_TYPES.Property || prop.value.type !== types.AST_NODE_TYPES.AssignmentPattern) continue;
@@ -2263,13 +2265,10 @@ var no_unstable_default_props_default = createRule({
2263
2265
  }
2264
2266
  },
2265
2267
  "VariableDeclarator[id.type='ObjectPattern'][init.type='Identifier']"(node) {
2266
- eff.O.map(
2267
- ctx.getCurrentFunction(),
2268
- ([_, currentFn]) => possibleDestructuringDeclarators.set(currentFn, [
2269
- ...possibleDestructuringDeclarators.get(currentFn) ?? [],
2270
- node
2271
- ])
2272
- );
2268
+ for (const [_, currentFn] of eff.O.toArray(ctx.getCurrentFunction())) {
2269
+ const prevDeclarators = declarators.get(currentFn) ?? [];
2270
+ declarators.set(currentFn, [...prevDeclarators, node]);
2271
+ }
2273
2272
  }
2274
2273
  };
2275
2274
  },
@@ -2397,7 +2396,9 @@ var no_unused_class_component_members_default = createRule({
2397
2396
  if (node.init && AST11__namespace.isThisExpression(node.init) && node.id.type === types.AST_NODE_TYPES.ObjectPattern) {
2398
2397
  for (const prop of node.id.properties) {
2399
2398
  if (prop.type === types.AST_NODE_TYPES.Property && AST11__namespace.isKeyLiteralLike(prop, prop.key)) {
2400
- eff.O.map(getName3(prop.key), (name2) => propertyUsages.get(currentClass)?.add(name2));
2399
+ for (const name2 of eff.O.toArray(getName3(prop.key))) {
2400
+ propertyUsages.get(currentClass)?.add(name2);
2401
+ }
2401
2402
  }
2402
2403
  }
2403
2404
  }
@@ -2552,29 +2553,38 @@ var no_unused_state_default = createRule({
2552
2553
  defaultOptions: []
2553
2554
  });
2554
2555
  var RULE_NAME44 = "no-useless-fragment";
2555
- function check(node, context, allowExpressions) {
2556
+ var defaultOptions = [{
2557
+ allowExpressions: true
2558
+ }];
2559
+ function checkAndReport(node, context, allowExpressions) {
2556
2560
  const initialScope = context.sourceCode.getScope(node);
2557
2561
  if (JSX7__namespace.isKeyedElement(node, initialScope)) return;
2558
2562
  if (JSX7__namespace.isBuiltInElement(node.parent)) context.report({ messageId: "noUselessFragmentInBuiltIn", node });
2559
2563
  if (node.children.length === 0) return context.report({ messageId: "noUselessFragment", node });
2560
- const isChildren = AST11__namespace.isOneOf([types.AST_NODE_TYPES.JSXElement, types.AST_NODE_TYPES.JSXFragment])(node.parent);
2561
- const [firstChildren] = node.children;
2562
- if (allowExpressions && node.children.length === 1 && JSX7__namespace.isLiteral(firstChildren) && !isChildren) return;
2563
- if (!allowExpressions && isChildren) {
2564
- return context.report({ messageId: "noUselessFragment", node });
2565
- } else if (!allowExpressions && !isChildren && node.children.length === 1) {
2566
- return context.report({ messageId: "noUselessFragment", node });
2564
+ const isChildElement = AST11__namespace.isOneOf([types.AST_NODE_TYPES.JSXElement, types.AST_NODE_TYPES.JSXFragment])(node.parent);
2565
+ switch (true) {
2566
+ // <Foo content={<>ee eeee eeee ...</>} />
2567
+ case (allowExpressions && !isChildElement && node.children.length === 1 && JSX7__namespace.isLiteral(node.children.at(0))): {
2568
+ return;
2569
+ }
2570
+ // <Foo><>hello, world</></Foo>
2571
+ case (!allowExpressions && isChildElement): {
2572
+ return context.report({ messageId: "noUselessFragment", node });
2573
+ }
2574
+ case (!allowExpressions && !isChildElement && node.children.length === 1): {
2575
+ return context.report({ messageId: "noUselessFragment", node });
2576
+ }
2567
2577
  }
2568
2578
  const nonPaddingChildren = node.children.filter((child) => !JSX7__namespace.isPaddingSpaces(child));
2569
- if (nonPaddingChildren.length > 1) return;
2570
- if (nonPaddingChildren.length === 0) return context.report({ messageId: "noUselessFragment", node });
2571
- const [first] = nonPaddingChildren;
2572
- if (tsPattern.isMatching({ type: types.AST_NODE_TYPES.JSXExpressionContainer, expression: tsPattern.P.not(types.AST_NODE_TYPES.CallExpression) }, first)) return;
2573
- context.report({ messageId: "noUselessFragment", node });
2579
+ const firstNonPaddingChild = nonPaddingChildren.at(0);
2580
+ switch (true) {
2581
+ case nonPaddingChildren.length === 0:
2582
+ case (nonPaddingChildren.length === 1 && firstNonPaddingChild?.type !== types.AST_NODE_TYPES.JSXExpressionContainer): {
2583
+ return context.report({ messageId: "noUselessFragment", node });
2584
+ }
2585
+ }
2586
+ return;
2574
2587
  }
2575
- var defaultOptions = [{
2576
- allowExpressions: true
2577
- }];
2578
2588
  var no_useless_fragment_default = createRule({
2579
2589
  meta: {
2580
2590
  type: "problem",
@@ -2602,11 +2612,11 @@ var no_useless_fragment_default = createRule({
2602
2612
  const { allowExpressions = true } = option;
2603
2613
  return {
2604
2614
  JSXElement(node) {
2605
- if (!core.isFragmentElement(node, context)) return;
2606
- check(node, context, allowExpressions);
2615
+ if (JSX7__namespace.getElementName(node.openingElement).split(".").at(-1) !== "Fragment") return;
2616
+ checkAndReport(node, context, allowExpressions);
2607
2617
  },
2608
2618
  JSXFragment(node) {
2609
- check(node, context, allowExpressions);
2619
+ checkAndReport(node, context, allowExpressions);
2610
2620
  }
2611
2621
  };
2612
2622
  },
@@ -2844,7 +2854,7 @@ var prefer_shorthand_fragment_default = createRule({
2844
2854
  name: RULE_NAME49,
2845
2855
  create(context) {
2846
2856
  function getReportDescriptor(node) {
2847
- if (!core.isFragmentElement(node, context)) return eff.O.none();
2857
+ if (JSX7__namespace.getElementName(node.openingElement).split(".").at(-1) !== "Fragment") return eff.O.none();
2848
2858
  const hasAttributes = node.openingElement.attributes.length > 0;
2849
2859
  if (hasAttributes) return eff.O.none();
2850
2860
  return eff.O.some({
@@ -2864,10 +2874,8 @@ var use_jsx_vars_default = createRule({
2864
2874
  meta: {
2865
2875
  type: "problem",
2866
2876
  docs: {
2867
- description: (
2868
- // eslint-disable-next-line eslint-plugin/require-meta-docs-description
2869
- "helpes `eslint/no-unused-vars` to correctly mark JSX variables as used."
2870
- ),
2877
+ // eslint-disable-next-line eslint-plugin/require-meta-docs-description
2878
+ description: "helpes `eslint/no-unused-vars` to correctly mark JSX variables as used.",
2871
2879
  [Symbol.for("rule_features")]: RULE_FEATURES49
2872
2880
  },
2873
2881
  messages: {
@@ -2890,9 +2898,9 @@ var use_jsx_vars_default = createRule({
2890
2898
  return {
2891
2899
  JSXOpeningElement(node) {
2892
2900
  if (node.name.type === types.AST_NODE_TYPES.JSXIdentifier && /^[a-z]/u.test(node.name.name)) return;
2893
- eff.O.map(getName5(node.name), (name2) => {
2901
+ for (const name2 of eff.O.toArray(getName5(node.name))) {
2894
2902
  context.sourceCode.markVariableAsUsed(name2, node);
2895
- });
2903
+ }
2896
2904
  }
2897
2905
  };
2898
2906
  },
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
- import { F, O, isString, or, isNullable } from '@eslint-react/eff';
1
+ import { F, O, or, isString, isNullable } from '@eslint-react/eff';
2
2
  import * as JSX7 from '@eslint-react/jsx';
3
3
  import { createRuleForPlugin, normalizeSettings, decodeSettings, unsafeReadSettings } from '@eslint-react/shared';
4
4
  import * as AST11 from '@eslint-react/ast';
5
- import { isForwardRefCall, isThisSetState, isClassComponent, isChildrenCount, isChildrenForEach, isChildrenMap, isChildrenOnly, isChildrenToArray, useComponentCollectorLegacy, isCloneElementCall, isCreateRefCall, isComponentName, useComponentCollector, ERFunctionComponentFlag, isChildrenToArrayCall, ERComponentHint, isDirectValueOfRenderPropertyLoose, isDeclaredInRenderPropLoose, isInsideCreateElementProps, isInsideRenderMethod, ERClassComponentFlag, isFragmentElement, isCreateElementCall, isInitializedFromReact } from '@eslint-react/core';
5
+ import { isForwardRefCall, isThisSetState, isClassComponent, isCreateElementCall, isCloneElementCall, isChildrenCount, isChildrenForEach, isChildrenMap, isChildrenOnly, isChildrenToArray, useComponentCollectorLegacy, isCreateRefCall, isComponentName, useComponentCollector, ERFunctionComponentFlag, isChildrenToArrayCall, ERComponentHint, isDirectValueOfRenderPropertyLoose, isDeclaredInRenderPropLoose, isInsideCreateElementProps, isInsideRenderMethod, ERClassComponentFlag, isInitializedFromReact } from '@eslint-react/core';
6
6
  import { AST_NODE_TYPES } from '@typescript-eslint/types';
7
7
  import { isMatching, P, match } from 'ts-pattern';
8
8
  import { compare } from 'compare-versions';
@@ -15,7 +15,7 @@ import { getTypeImmutability, isUnknown, isImmutable, isReadonlyShallow, isReado
15
15
 
16
16
  // package.json
17
17
  var name = "eslint-plugin-react-x";
18
- var version = "1.22.2-next.9";
18
+ var version = "1.23.0-beta.0";
19
19
  var createRule = createRuleForPlugin("x");
20
20
 
21
21
  // src/rules/avoid-shorthand-boolean.ts
@@ -300,12 +300,10 @@ var no_array_index_key_default = createRule({
300
300
  name: RULE_NAME5,
301
301
  create(context) {
302
302
  const indexParamNames = [];
303
+ const isCreateOrCloneElementCall = or(isCreateElementCall(context), isCloneElementCall(context));
303
304
  function isArrayIndex(node) {
304
305
  return node.type === AST_NODE_TYPES.Identifier && indexParamNames.some(O.exists((name2) => name2 === node.name));
305
306
  }
306
- function isCreateOrCloneElementCall(node) {
307
- return isCreateElementCall(node, context) || isCloneElementCall(node, context);
308
- }
309
307
  function getReportDescriptor(node) {
310
308
  if (isArrayIndex(node)) return [{ messageId: "noArrayIndexKey", node }];
311
309
  if (AST11.isOneOf([AST_NODE_TYPES.TemplateLiteral, AST_NODE_TYPES.BinaryExpression])(node)) {
@@ -1835,9 +1833,15 @@ var no_set_state_in_component_did_mount_default = createRule({
1835
1833
  O.Do,
1836
1834
  O.bind("clazz", () => AST11.traverseUpGuard(node, isClassComponent)),
1837
1835
  O.bind("method", ({ clazz }) => AST11.traverseUpStop(node, clazz, isComponentDidMount)),
1836
+ O.bind("methodScope", ({ method }) => O.some(context.sourceCode.getScope(method))),
1838
1837
  O.bind("upperScope", () => O.fromNullable(context.sourceCode.getScope(node).upper)),
1839
1838
  O.filter(
1840
- ({ clazz, method, upperScope }) => method.parent === clazz.body && upperScope === context.sourceCode.getScope(method)
1839
+ ({
1840
+ clazz,
1841
+ method,
1842
+ methodScope,
1843
+ upperScope
1844
+ }) => method.parent === clazz.body && upperScope === methodScope
1841
1845
  ),
1842
1846
  O.map(() => ({
1843
1847
  messageId: "noSetStateInComponentDidMount",
@@ -2129,39 +2133,40 @@ var no_unstable_context_value_default = createRule({
2129
2133
  name: RULE_NAME40,
2130
2134
  create(context) {
2131
2135
  const { ctx, listeners } = useComponentCollector(context);
2132
- const possibleValueConstructions = /* @__PURE__ */ new Map();
2136
+ const constructions = /* @__PURE__ */ new Map();
2133
2137
  return {
2134
2138
  ...listeners,
2135
2139
  JSXOpeningElement(node) {
2136
2140
  const openingElementName = node.name;
2137
2141
  if (openingElementName.type !== AST_NODE_TYPES.JSXMemberExpression) return;
2138
2142
  if (openingElementName.property.name !== "Provider") return;
2139
- const maybeJSXValueAttribute = O.fromNullable(
2140
- node.attributes.find((attribute) => {
2141
- return attribute.type === AST_NODE_TYPES.JSXAttribute && attribute.name.name === "value";
2142
- })
2143
+ const constructionEntry = F.pipe(
2144
+ O.Do,
2145
+ O.bind("function", ctx.getCurrentFunction),
2146
+ O.bind("attribute", () => O.fromNullable(
2147
+ node.attributes.find((attribute) => {
2148
+ return attribute.type === AST_NODE_TYPES.JSXAttribute && attribute.name.name === "value";
2149
+ })
2150
+ )),
2151
+ O.bind("value", ({ attribute }) => "value" in attribute ? O.some(attribute.value) : O.none()),
2152
+ O.bind("valueExpression", ({ value }) => value?.type === AST_NODE_TYPES.JSXExpressionContainer ? O.some(value.expression) : O.none()),
2153
+ O.bind("construction", ({ valueExpression }) => {
2154
+ const initialScope = context.sourceCode.getScope(valueExpression);
2155
+ return O.some(VAR.inspectConstruction(valueExpression, initialScope));
2156
+ }),
2157
+ O.filter(({ construction }) => construction._tag !== "None")
2143
2158
  );
2144
- if (O.isNone(maybeJSXValueAttribute) || !("value" in maybeJSXValueAttribute.value)) return;
2145
- const valueNode = maybeJSXValueAttribute.value.value;
2146
- if (valueNode?.type !== AST_NODE_TYPES.JSXExpressionContainer) return;
2147
- const valueExpression = valueNode.expression;
2148
- const initialScope = context.sourceCode.getScope(valueExpression);
2149
- const construction = VAR.inspectConstruction(valueExpression, initialScope);
2150
- if (construction._tag === "None") return;
2151
- O.map(
2152
- ctx.getCurrentFunction(),
2153
- ([_, currentFn]) => possibleValueConstructions.set(currentFn, [
2154
- ...possibleValueConstructions.get(currentFn) ?? [],
2159
+ for (const { construction, function: [_, fNode] } of O.toArray(constructionEntry)) {
2160
+ constructions.set(fNode, [
2161
+ ...constructions.get(fNode) ?? [],
2155
2162
  construction
2156
- ])
2157
- );
2163
+ ]);
2164
+ }
2158
2165
  },
2159
2166
  "Program:exit"(node) {
2160
2167
  const components = ctx.getAllComponents(node).values();
2161
2168
  for (const { node: component } of components) {
2162
- const constructions = possibleValueConstructions.get(component);
2163
- if (!constructions) continue;
2164
- for (const construction of constructions) {
2169
+ for (const construction of constructions.get(component) ?? []) {
2165
2170
  if (construction._tag === "None") continue;
2166
2171
  const { node: constructionNode, _tag } = construction;
2167
2172
  const messageId = _tag.startsWith("Function") ? "noUnstableContextValueWithFunction" : "noUnstableContextValueWithIdentifier";
@@ -2198,7 +2203,7 @@ var no_unstable_default_props_default = createRule({
2198
2203
  name: RULE_NAME41,
2199
2204
  create(context) {
2200
2205
  const { ctx, listeners } = useComponentCollector(context);
2201
- const possibleDestructuringDeclarators = /* @__PURE__ */ new WeakMap();
2206
+ const declarators = /* @__PURE__ */ new WeakMap();
2202
2207
  return {
2203
2208
  ...listeners,
2204
2209
  "Program:exit"(node) {
@@ -2208,10 +2213,7 @@ var no_unstable_default_props_default = createRule({
2208
2213
  const [props] = params;
2209
2214
  if (!props) continue;
2210
2215
  const properties = match(props).with({ type: AST_NODE_TYPES.ObjectPattern }, ({ properties: properties2 }) => properties2).with({ type: AST_NODE_TYPES.Identifier }, ({ name: name2 }) => {
2211
- const variableDeclarators = possibleDestructuringDeclarators.get(component);
2212
- if (!variableDeclarators) return [];
2213
- const declarators = variableDeclarators.filter((d) => d.init.name === name2);
2214
- return declarators.flatMap((d) => d.id.properties);
2216
+ return declarators.get(component)?.filter((d) => d.init.name === name2).flatMap((d) => d.id.properties) ?? [];
2215
2217
  }).otherwise(() => []);
2216
2218
  for (const prop of properties) {
2217
2219
  if (prop.type !== AST_NODE_TYPES.Property || prop.value.type !== AST_NODE_TYPES.AssignmentPattern) continue;
@@ -2236,13 +2238,10 @@ var no_unstable_default_props_default = createRule({
2236
2238
  }
2237
2239
  },
2238
2240
  "VariableDeclarator[id.type='ObjectPattern'][init.type='Identifier']"(node) {
2239
- O.map(
2240
- ctx.getCurrentFunction(),
2241
- ([_, currentFn]) => possibleDestructuringDeclarators.set(currentFn, [
2242
- ...possibleDestructuringDeclarators.get(currentFn) ?? [],
2243
- node
2244
- ])
2245
- );
2241
+ for (const [_, currentFn] of O.toArray(ctx.getCurrentFunction())) {
2242
+ const prevDeclarators = declarators.get(currentFn) ?? [];
2243
+ declarators.set(currentFn, [...prevDeclarators, node]);
2244
+ }
2246
2245
  }
2247
2246
  };
2248
2247
  },
@@ -2370,7 +2369,9 @@ var no_unused_class_component_members_default = createRule({
2370
2369
  if (node.init && AST11.isThisExpression(node.init) && node.id.type === AST_NODE_TYPES.ObjectPattern) {
2371
2370
  for (const prop of node.id.properties) {
2372
2371
  if (prop.type === AST_NODE_TYPES.Property && AST11.isKeyLiteralLike(prop, prop.key)) {
2373
- O.map(getName3(prop.key), (name2) => propertyUsages.get(currentClass)?.add(name2));
2372
+ for (const name2 of O.toArray(getName3(prop.key))) {
2373
+ propertyUsages.get(currentClass)?.add(name2);
2374
+ }
2374
2375
  }
2375
2376
  }
2376
2377
  }
@@ -2525,29 +2526,38 @@ var no_unused_state_default = createRule({
2525
2526
  defaultOptions: []
2526
2527
  });
2527
2528
  var RULE_NAME44 = "no-useless-fragment";
2528
- function check(node, context, allowExpressions) {
2529
+ var defaultOptions = [{
2530
+ allowExpressions: true
2531
+ }];
2532
+ function checkAndReport(node, context, allowExpressions) {
2529
2533
  const initialScope = context.sourceCode.getScope(node);
2530
2534
  if (JSX7.isKeyedElement(node, initialScope)) return;
2531
2535
  if (JSX7.isBuiltInElement(node.parent)) context.report({ messageId: "noUselessFragmentInBuiltIn", node });
2532
2536
  if (node.children.length === 0) return context.report({ messageId: "noUselessFragment", node });
2533
- const isChildren = AST11.isOneOf([AST_NODE_TYPES.JSXElement, AST_NODE_TYPES.JSXFragment])(node.parent);
2534
- const [firstChildren] = node.children;
2535
- if (allowExpressions && node.children.length === 1 && JSX7.isLiteral(firstChildren) && !isChildren) return;
2536
- if (!allowExpressions && isChildren) {
2537
- return context.report({ messageId: "noUselessFragment", node });
2538
- } else if (!allowExpressions && !isChildren && node.children.length === 1) {
2539
- return context.report({ messageId: "noUselessFragment", node });
2537
+ const isChildElement = AST11.isOneOf([AST_NODE_TYPES.JSXElement, AST_NODE_TYPES.JSXFragment])(node.parent);
2538
+ switch (true) {
2539
+ // <Foo content={<>ee eeee eeee ...</>} />
2540
+ case (allowExpressions && !isChildElement && node.children.length === 1 && JSX7.isLiteral(node.children.at(0))): {
2541
+ return;
2542
+ }
2543
+ // <Foo><>hello, world</></Foo>
2544
+ case (!allowExpressions && isChildElement): {
2545
+ return context.report({ messageId: "noUselessFragment", node });
2546
+ }
2547
+ case (!allowExpressions && !isChildElement && node.children.length === 1): {
2548
+ return context.report({ messageId: "noUselessFragment", node });
2549
+ }
2540
2550
  }
2541
2551
  const nonPaddingChildren = node.children.filter((child) => !JSX7.isPaddingSpaces(child));
2542
- if (nonPaddingChildren.length > 1) return;
2543
- if (nonPaddingChildren.length === 0) return context.report({ messageId: "noUselessFragment", node });
2544
- const [first] = nonPaddingChildren;
2545
- if (isMatching({ type: AST_NODE_TYPES.JSXExpressionContainer, expression: P.not(AST_NODE_TYPES.CallExpression) }, first)) return;
2546
- context.report({ messageId: "noUselessFragment", node });
2552
+ const firstNonPaddingChild = nonPaddingChildren.at(0);
2553
+ switch (true) {
2554
+ case nonPaddingChildren.length === 0:
2555
+ case (nonPaddingChildren.length === 1 && firstNonPaddingChild?.type !== AST_NODE_TYPES.JSXExpressionContainer): {
2556
+ return context.report({ messageId: "noUselessFragment", node });
2557
+ }
2558
+ }
2559
+ return;
2547
2560
  }
2548
- var defaultOptions = [{
2549
- allowExpressions: true
2550
- }];
2551
2561
  var no_useless_fragment_default = createRule({
2552
2562
  meta: {
2553
2563
  type: "problem",
@@ -2575,11 +2585,11 @@ var no_useless_fragment_default = createRule({
2575
2585
  const { allowExpressions = true } = option;
2576
2586
  return {
2577
2587
  JSXElement(node) {
2578
- if (!isFragmentElement(node, context)) return;
2579
- check(node, context, allowExpressions);
2588
+ if (JSX7.getElementName(node.openingElement).split(".").at(-1) !== "Fragment") return;
2589
+ checkAndReport(node, context, allowExpressions);
2580
2590
  },
2581
2591
  JSXFragment(node) {
2582
- check(node, context, allowExpressions);
2592
+ checkAndReport(node, context, allowExpressions);
2583
2593
  }
2584
2594
  };
2585
2595
  },
@@ -2817,7 +2827,7 @@ var prefer_shorthand_fragment_default = createRule({
2817
2827
  name: RULE_NAME49,
2818
2828
  create(context) {
2819
2829
  function getReportDescriptor(node) {
2820
- if (!isFragmentElement(node, context)) return O.none();
2830
+ if (JSX7.getElementName(node.openingElement).split(".").at(-1) !== "Fragment") return O.none();
2821
2831
  const hasAttributes = node.openingElement.attributes.length > 0;
2822
2832
  if (hasAttributes) return O.none();
2823
2833
  return O.some({
@@ -2837,10 +2847,8 @@ var use_jsx_vars_default = createRule({
2837
2847
  meta: {
2838
2848
  type: "problem",
2839
2849
  docs: {
2840
- description: (
2841
- // eslint-disable-next-line eslint-plugin/require-meta-docs-description
2842
- "helpes `eslint/no-unused-vars` to correctly mark JSX variables as used."
2843
- ),
2850
+ // eslint-disable-next-line eslint-plugin/require-meta-docs-description
2851
+ description: "helpes `eslint/no-unused-vars` to correctly mark JSX variables as used.",
2844
2852
  [Symbol.for("rule_features")]: RULE_FEATURES49
2845
2853
  },
2846
2854
  messages: {
@@ -2863,9 +2871,9 @@ var use_jsx_vars_default = createRule({
2863
2871
  return {
2864
2872
  JSXOpeningElement(node) {
2865
2873
  if (node.name.type === AST_NODE_TYPES.JSXIdentifier && /^[a-z]/u.test(node.name.name)) return;
2866
- O.map(getName5(node.name), (name2) => {
2874
+ for (const name2 of O.toArray(getName5(node.name))) {
2867
2875
  context.sourceCode.markVariableAsUsed(name2, node);
2868
- });
2876
+ }
2869
2877
  }
2870
2878
  };
2871
2879
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-x",
3
- "version": "1.22.2-next.9",
3
+ "version": "1.23.0-beta.0",
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",
@@ -49,13 +49,13 @@
49
49
  "string-ts": "^2.2.0",
50
50
  "ts-api-utils": "^2.0.0",
51
51
  "ts-pattern": "^5.6.0",
52
- "@eslint-react/ast": "1.22.2-next.9",
53
- "@eslint-react/core": "1.22.2-next.9",
54
- "@eslint-react/jsx": "1.22.2-next.9",
55
- "@eslint-react/eff": "1.22.2-next.9",
56
- "@eslint-react/shared": "1.22.2-next.9",
57
- "@eslint-react/types": "1.22.2-next.9",
58
- "@eslint-react/var": "1.22.2-next.9"
52
+ "@eslint-react/core": "1.23.0-beta.0",
53
+ "@eslint-react/ast": "1.23.0-beta.0",
54
+ "@eslint-react/eff": "1.23.0-beta.0",
55
+ "@eslint-react/jsx": "1.23.0-beta.0",
56
+ "@eslint-react/shared": "1.23.0-beta.0",
57
+ "@eslint-react/types": "1.23.0-beta.0",
58
+ "@eslint-react/var": "1.23.0-beta.0"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@types/react": "^19.0.2",