eslint-plugin-react-hooks-extra 1.23.2 → 1.23.3-beta.2

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 (3) hide show
  1. package/dist/index.js +166 -56
  2. package/dist/index.mjs +166 -56
  3. package/package.json +10 -10
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ var VAR5__namespace = /*#__PURE__*/_interopNamespace(VAR5);
31
31
 
32
32
  // package.json
33
33
  var name = "eslint-plugin-react-hooks-extra";
34
- var version = "1.23.2";
34
+ var version = "1.23.3-beta.2";
35
35
  var createRule = shared.createRuleForPlugin("hooks-extra");
36
36
  function isFromHookCall(name2, context, settings, predicate = eff.F.constTrue) {
37
37
  const hookAlias = settings.additionalHooks?.[name2] ?? [];
@@ -46,7 +46,9 @@ function isFromHookCall(name2, context, settings, predicate = eff.F.constTrue) {
46
46
  function isFromUseStateCall(context, settings) {
47
47
  const predicate = (topLevelId, call) => {
48
48
  const { parent } = call;
49
- if (!("id" in parent && parent.id?.type === types.AST_NODE_TYPES.ArrayPattern)) return true;
49
+ if (!("id" in parent && parent.id?.type === types.AST_NODE_TYPES.ArrayPattern)) {
50
+ return true;
51
+ }
50
52
  return parent.id.elements.findIndex((e) => e?.type === types.AST_NODE_TYPES.Identifier && e.name === topLevelId.name) === 1;
51
53
  };
52
54
  return isFromHookCall("useState", context, settings, predicate);
@@ -59,8 +61,12 @@ function isSetFunctionCall(context, settings) {
59
61
  // data.at(1)();
60
62
  case types.AST_NODE_TYPES.CallExpression: {
61
63
  const { callee } = node.callee;
62
- if (callee.type !== types.AST_NODE_TYPES.MemberExpression) return false;
63
- if (!("name" in callee.object)) return false;
64
+ if (callee.type !== types.AST_NODE_TYPES.MemberExpression) {
65
+ return false;
66
+ }
67
+ if (!("name" in callee.object)) {
68
+ return false;
69
+ }
64
70
  const isAt = tsPattern.isMatching({
65
71
  type: types.AST_NODE_TYPES.MemberExpression,
66
72
  property: {
@@ -69,7 +75,9 @@ function isSetFunctionCall(context, settings) {
69
75
  }
70
76
  }, callee);
71
77
  const [index] = node.callee.arguments;
72
- if (!isAt || !index) return false;
78
+ if (!isAt || !index) {
79
+ return false;
80
+ }
73
81
  const initialScope = context.sourceCode.getScope(node);
74
82
  return eff.O.exists(VAR5__namespace.getStaticValue(index, initialScope), (v) => v === 1) && isIdFromUseStateCall(callee.object);
75
83
  }
@@ -81,7 +89,9 @@ function isSetFunctionCall(context, settings) {
81
89
  // const data = useState();
82
90
  // data[1]();
83
91
  case types.AST_NODE_TYPES.MemberExpression: {
84
- if (!("name" in node.callee.object)) return false;
92
+ if (!("name" in node.callee.object)) {
93
+ return false;
94
+ }
85
95
  const initialScope = context.sourceCode.getScope(node);
86
96
  return eff.O.exists(VAR5__namespace.getStaticValue(node.callee.property, initialScope), (v) => v === 1) && isIdFromUseStateCall(node.callee.object);
87
97
  }
@@ -95,9 +105,15 @@ function isThenCall(node) {
95
105
  return node.callee.type === types.AST_NODE_TYPES.MemberExpression && node.callee.property.type === types.AST_NODE_TYPES.Identifier && node.callee.property.name === "then";
96
106
  }
97
107
  function isVariableDeclaratorFromHookCall(node) {
98
- if (node.type !== types.AST_NODE_TYPES.VariableDeclarator) return false;
99
- if (node.id.type !== types.AST_NODE_TYPES.Identifier) return false;
100
- if (node.init?.type !== types.AST_NODE_TYPES.CallExpression) return false;
108
+ if (node.type !== types.AST_NODE_TYPES.VariableDeclarator) {
109
+ return false;
110
+ }
111
+ if (node.id.type !== types.AST_NODE_TYPES.Identifier) {
112
+ return false;
113
+ }
114
+ if (node.init?.type !== types.AST_NODE_TYPES.CallExpression) {
115
+ return false;
116
+ }
101
117
  switch (node.init.callee.type) {
102
118
  case types.AST_NODE_TYPES.Identifier:
103
119
  return core.isReactHookName(node.init.callee.name);
@@ -127,7 +143,9 @@ var no_direct_set_state_in_use_effect_default = createRule({
127
143
  },
128
144
  name: RULE_NAME,
129
145
  create(context) {
130
- if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
146
+ if (!/use\w*Effect/u.test(context.sourceCode.text)) {
147
+ return {};
148
+ }
131
149
  const settings = shared.getSettingsFromContext(context);
132
150
  const additionalHooks = settings.additionalHooks ?? {};
133
151
  const isUseEffectLikeCall = core.isReactHookCallWithNameAlias("useEffect", context, additionalHooks.useEffect ?? []);
@@ -177,9 +195,13 @@ var no_direct_set_state_in_use_effect_default = createRule({
177
195
  CallExpression(node) {
178
196
  const setupFunction = eff.O.getOrNull(setupFunctionRef.current);
179
197
  const pEntry = functionStack.at(-1);
180
- if (pEntry?.node.async) return;
198
+ if (pEntry?.node.async) {
199
+ return;
200
+ }
181
201
  tsPattern.match(getCallKind(node)).with("setState", () => {
182
- if (!pEntry) return;
202
+ if (!pEntry) {
203
+ return;
204
+ }
183
205
  switch (true) {
184
206
  case (pEntry.node === setupFunction || pEntry.kind === "immediate"): {
185
207
  context.report({
@@ -204,33 +226,51 @@ var no_direct_set_state_in_use_effect_default = createRule({
204
226
  }
205
227
  }
206
228
  }).with("useEffect", () => {
207
- if (AST2__namespace.isFunction(node.arguments.at(0))) return;
229
+ if (AST2__namespace.isFunction(node.arguments.at(0))) {
230
+ return;
231
+ }
208
232
  setupFunctionIdentifiers.push(...AST2__namespace.getNestedIdentifiers(node));
209
233
  }).with("other", () => {
210
- if (pEntry?.node !== setupFunction) return;
234
+ if (pEntry?.node !== setupFunction) {
235
+ return;
236
+ }
211
237
  indFunctionCalls.push(node);
212
238
  }).otherwise(eff.F.constVoid);
213
239
  },
214
240
  Identifier(node) {
215
- if (node.parent.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee === node) return;
216
- if (!isIdFromUseStateCall(node)) return;
241
+ if (node.parent.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee === node) {
242
+ return;
243
+ }
244
+ if (!isIdFromUseStateCall(node)) {
245
+ return;
246
+ }
217
247
  switch (node.parent.type) {
218
248
  case types.AST_NODE_TYPES.ArrowFunctionExpression: {
219
249
  const parent = node.parent.parent;
220
- if (parent.type !== types.AST_NODE_TYPES.CallExpression) break;
221
- if (!isUseMemoCall2(parent)) break;
250
+ if (parent.type !== types.AST_NODE_TYPES.CallExpression) {
251
+ break;
252
+ }
253
+ if (!isUseMemoCall2(parent)) {
254
+ break;
255
+ }
222
256
  const mbVariableDeclarator = AST2__namespace.findParentNodeGuard(parent, isVariableDeclaratorFromHookCall);
223
- if (eff.O.isNone(mbVariableDeclarator)) break;
257
+ if (eff.O.isNone(mbVariableDeclarator)) {
258
+ break;
259
+ }
224
260
  const variableDeclarator = mbVariableDeclarator.value;
225
261
  const calls = indSetStateCallsInUseEffectArg0.get(variableDeclarator.init) ?? [];
226
262
  indSetStateCallsInUseEffectArg0.set(variableDeclarator.init, [...calls, node]);
227
263
  break;
228
264
  }
229
265
  case types.AST_NODE_TYPES.CallExpression: {
230
- if (node !== node.parent.arguments.at(0)) break;
266
+ if (node !== node.parent.arguments.at(0)) {
267
+ break;
268
+ }
231
269
  if (isUseCallbackCall2(node.parent)) {
232
270
  const mbVariableDeclarator = AST2__namespace.findParentNodeGuard(node.parent, isVariableDeclaratorFromHookCall);
233
- if (eff.O.isNone(mbVariableDeclarator)) break;
271
+ if (eff.O.isNone(mbVariableDeclarator)) {
272
+ break;
273
+ }
234
274
  const variableDeclarator = mbVariableDeclarator.value;
235
275
  const prevs = indSetStateCallsInUseEffectArg0.get(variableDeclarator.init) ?? [];
236
276
  indSetStateCallsInUseEffectArg0.set(variableDeclarator.init, [...prevs, node]);
@@ -266,7 +306,9 @@ var no_direct_set_state_in_use_effect_default = createRule({
266
306
  }
267
307
  }
268
308
  for (const { callee } of indFunctionCalls) {
269
- if (!("name" in callee)) continue;
309
+ if (!("name" in callee)) {
310
+ continue;
311
+ }
270
312
  const { name: name2 } = callee;
271
313
  const setStateCalls = getSetStateCalls(name2, context.sourceCode.getScope(callee));
272
314
  for (const setStateCall of setStateCalls) {
@@ -314,7 +356,9 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
314
356
  },
315
357
  name: RULE_NAME2,
316
358
  create(context) {
317
- if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
359
+ if (!/use\w*Effect/u.test(context.sourceCode.text)) {
360
+ return {};
361
+ }
318
362
  const settings = shared.getSettingsFromContext(context);
319
363
  const additionalHooks = settings.additionalHooks ?? {};
320
364
  const isUseLayoutEffectLikeCall = core.isReactHookCallWithNameAlias(
@@ -368,9 +412,13 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
368
412
  CallExpression(node) {
369
413
  const setupFunction = eff.O.getOrNull(setupFunctionRef.current);
370
414
  const pEntry = functionStack.at(-1);
371
- if (pEntry?.node.async) return;
415
+ if (pEntry?.node.async) {
416
+ return;
417
+ }
372
418
  tsPattern.match(getCallKind(node)).with("setState", () => {
373
- if (!pEntry) return;
419
+ if (!pEntry) {
420
+ return;
421
+ }
374
422
  switch (true) {
375
423
  case (pEntry.node === setupFunction || pEntry.kind === "immediate"): {
376
424
  context.report({
@@ -395,33 +443,51 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
395
443
  }
396
444
  }
397
445
  }).with("useLayoutEffect", () => {
398
- if (AST2__namespace.isFunction(node.arguments.at(0))) return;
446
+ if (AST2__namespace.isFunction(node.arguments.at(0))) {
447
+ return;
448
+ }
399
449
  setupFunctionIdentifiers.push(...AST2__namespace.getNestedIdentifiers(node));
400
450
  }).with("other", () => {
401
- if (pEntry?.node !== setupFunction) return;
451
+ if (pEntry?.node !== setupFunction) {
452
+ return;
453
+ }
402
454
  indFunctionCalls.push(node);
403
455
  }).otherwise(eff.F.constVoid);
404
456
  },
405
457
  Identifier(node) {
406
- if (node.parent.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee === node) return;
407
- if (!isIdFromUseStateCall(node)) return;
458
+ if (node.parent.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee === node) {
459
+ return;
460
+ }
461
+ if (!isIdFromUseStateCall(node)) {
462
+ return;
463
+ }
408
464
  switch (node.parent.type) {
409
465
  case types.AST_NODE_TYPES.ArrowFunctionExpression: {
410
466
  const parent = node.parent.parent;
411
- if (parent.type !== types.AST_NODE_TYPES.CallExpression) break;
412
- if (!isUseMemoCall2(parent)) break;
467
+ if (parent.type !== types.AST_NODE_TYPES.CallExpression) {
468
+ break;
469
+ }
470
+ if (!isUseMemoCall2(parent)) {
471
+ break;
472
+ }
413
473
  const mbVariableDeclarator = AST2__namespace.findParentNodeGuard(parent, isVariableDeclaratorFromHookCall);
414
- if (eff.O.isNone(mbVariableDeclarator)) break;
474
+ if (eff.O.isNone(mbVariableDeclarator)) {
475
+ break;
476
+ }
415
477
  const variableDeclarator = mbVariableDeclarator.value;
416
478
  const calls = indSetStateCallsInUseLayoutEffectArg0.get(variableDeclarator.init) ?? [];
417
479
  indSetStateCallsInUseLayoutEffectArg0.set(variableDeclarator.init, [...calls, node]);
418
480
  break;
419
481
  }
420
482
  case types.AST_NODE_TYPES.CallExpression: {
421
- if (node !== node.parent.arguments.at(0)) break;
483
+ if (node !== node.parent.arguments.at(0)) {
484
+ break;
485
+ }
422
486
  if (isUseCallbackCall2(node.parent)) {
423
487
  const mbVariableDeclarator = AST2__namespace.findParentNodeGuard(node.parent, isVariableDeclaratorFromHookCall);
424
- if (eff.O.isNone(mbVariableDeclarator)) break;
488
+ if (eff.O.isNone(mbVariableDeclarator)) {
489
+ break;
490
+ }
425
491
  const variableDeclarator = mbVariableDeclarator.value;
426
492
  const prevs = indSetStateCallsInUseLayoutEffectArg0.get(variableDeclarator.init) ?? [];
427
493
  indSetStateCallsInUseLayoutEffectArg0.set(variableDeclarator.init, [...prevs, node]);
@@ -457,7 +523,9 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
457
523
  }
458
524
  }
459
525
  for (const { callee } of indFunctionCalls) {
460
- if (!("name" in callee)) continue;
526
+ if (!("name" in callee)) {
527
+ continue;
528
+ }
461
529
  const { name: name2 } = callee;
462
530
  const setStateCalls = getSetStateCalls(name2, context.sourceCode.getScope(callee));
463
531
  for (const setStateCall of setStateCalls) {
@@ -505,18 +573,28 @@ var no_unnecessary_use_callback_default = createRule({
505
573
  },
506
574
  name: RULE_NAME3,
507
575
  create(context) {
508
- if (!context.sourceCode.text.includes("use")) return {};
576
+ if (!context.sourceCode.text.includes("use")) {
577
+ return {};
578
+ }
509
579
  const alias = shared.getSettingsFromContext(context).additionalHooks?.useCallback ?? [];
510
580
  return {
511
581
  CallExpression(node) {
512
- if (!core.isReactHookCall(node)) return;
582
+ if (!core.isReactHookCall(node)) {
583
+ return;
584
+ }
513
585
  const initialScope = context.sourceCode.getScope(node);
514
- if (!core.isUseCallbackCall(node, context) && !alias.some(core.isReactHookCallWithNameLoose(node))) return;
586
+ if (!core.isUseCallbackCall(node, context) && !alias.some(core.isReactHookCallWithNameLoose(node))) {
587
+ return;
588
+ }
515
589
  const scope = context.sourceCode.getScope(node);
516
590
  const component = scope.block;
517
- if (!AST2__namespace.isFunction(component)) return;
591
+ if (!AST2__namespace.isFunction(component)) {
592
+ return;
593
+ }
518
594
  const [arg0, arg1] = node.arguments;
519
- if (!arg0 || !arg1) return;
595
+ if (!arg0 || !arg1) {
596
+ return;
597
+ }
520
598
  const hasEmptyDeps = eff.F.pipe(
521
599
  tsPattern.match(arg1).with({ type: types.AST_NODE_TYPES.ArrayExpression }, eff.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
522
600
  return eff.F.pipe(
@@ -527,7 +605,9 @@ var no_unnecessary_use_callback_default = createRule({
527
605
  }).otherwise(eff.O.none),
528
606
  eff.O.exists((x) => x.elements.length === 0)
529
607
  );
530
- if (!hasEmptyDeps) return;
608
+ if (!hasEmptyDeps) {
609
+ return;
610
+ }
531
611
  const isReferencedToComponentScope = eff.F.pipe(
532
612
  tsPattern.match(arg0).with({ type: types.AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
533
613
  if (n.body.type === types.AST_NODE_TYPES.ArrowFunctionExpression) {
@@ -574,24 +654,36 @@ var no_unnecessary_use_memo_default = createRule({
574
654
  },
575
655
  name: RULE_NAME4,
576
656
  create(context) {
577
- if (!context.sourceCode.text.includes("use")) return {};
657
+ if (!context.sourceCode.text.includes("use")) {
658
+ return {};
659
+ }
578
660
  const alias = shared.getSettingsFromContext(context).additionalHooks?.useMemo ?? [];
579
661
  return {
580
662
  CallExpression(node) {
581
- if (!core.isReactHookCall(node)) return;
663
+ if (!core.isReactHookCall(node)) {
664
+ return;
665
+ }
582
666
  const initialScope = context.sourceCode.getScope(node);
583
- if (!core.isUseMemoCall(node, context) && !alias.some(core.isReactHookCallWithNameLoose(node))) return;
667
+ if (!core.isUseMemoCall(node, context) && !alias.some(core.isReactHookCallWithNameLoose(node))) {
668
+ return;
669
+ }
584
670
  const scope = context.sourceCode.getScope(node);
585
671
  const component = scope.block;
586
- if (!AST2__namespace.isFunction(component)) return;
672
+ if (!AST2__namespace.isFunction(component)) {
673
+ return;
674
+ }
587
675
  const [arg0, arg1] = node.arguments;
588
- if (!arg0 || !arg1) return;
676
+ if (!arg0 || !arg1) {
677
+ return;
678
+ }
589
679
  const hasCallInArg0 = eff.F.pipe(
590
680
  eff.O.some(arg0),
591
681
  eff.O.filter((n) => AST2__namespace.isFunction(n)),
592
682
  eff.O.exists((n) => [...AST2__namespace.getNestedCallExpressions(n.body), ...AST2__namespace.getNestedNewExpressions(n.body)].length > 0)
593
683
  );
594
- if (hasCallInArg0) return;
684
+ if (hasCallInArg0) {
685
+ return;
686
+ }
595
687
  const hasEmptyDeps = eff.F.pipe(
596
688
  tsPattern.match(arg1).with({ type: types.AST_NODE_TYPES.ArrayExpression }, eff.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
597
689
  return eff.F.pipe(
@@ -602,7 +694,9 @@ var no_unnecessary_use_memo_default = createRule({
602
694
  }).otherwise(eff.O.none),
603
695
  eff.O.exists((x) => x.elements.length === 0)
604
696
  );
605
- if (!hasEmptyDeps) return;
697
+ if (!hasEmptyDeps) {
698
+ return;
699
+ }
606
700
  const isReferencedToComponentScope = eff.F.pipe(
607
701
  tsPattern.match(arg0).with({ type: types.AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
608
702
  if (n.body.type === types.AST_NODE_TYPES.ArrowFunctionExpression) {
@@ -658,9 +752,15 @@ var no_useless_custom_hooks_default = createRule({
658
752
  "Program:exit"(node) {
659
753
  const allHooks = ctx.getAllHooks(node);
660
754
  for (const { name: name2, node: node2, hookCalls } of allHooks.values()) {
661
- if (AST2__namespace.isEmptyFunction(node2)) continue;
662
- if (hookCalls.length > 0) continue;
663
- if (isNodeContainsUseCallComments(node2, context)) continue;
755
+ if (AST2__namespace.isEmptyFunction(node2)) {
756
+ continue;
757
+ }
758
+ if (hookCalls.length > 0) {
759
+ continue;
760
+ }
761
+ if (isNodeContainsUseCallComments(node2, context)) {
762
+ continue;
763
+ }
664
764
  context.report({
665
765
  messageId: "noUselessCustomHooks",
666
766
  node: node2,
@@ -693,14 +793,22 @@ var prefer_use_state_lazy_initialization_default = createRule({
693
793
  },
694
794
  name: RULE_NAME6,
695
795
  create(context) {
696
- if (!context.sourceCode.text.includes("use")) return {};
796
+ if (!context.sourceCode.text.includes("use")) {
797
+ return {};
798
+ }
697
799
  const alias = shared.getSettingsFromContext(context).additionalHooks?.useState ?? [];
698
800
  return {
699
801
  CallExpression(node) {
700
- if (!core.isReactHookCall(node)) return;
701
- if (!core.isUseStateCall(node, context) && !alias.some(core.isReactHookCallWithNameLoose(node))) return;
802
+ if (!core.isReactHookCall(node)) {
803
+ return;
804
+ }
805
+ if (!core.isUseStateCall(node, context) && !alias.some(core.isReactHookCallWithNameLoose(node))) {
806
+ return;
807
+ }
702
808
  const [useStateInput] = node.arguments;
703
- if (!useStateInput) return;
809
+ if (!useStateInput) {
810
+ return;
811
+ }
704
812
  const nestedCallExpressions = AST2__namespace.getNestedCallExpressions(useStateInput);
705
813
  const hasFunctionCall = nestedCallExpressions.some((n) => {
706
814
  return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
@@ -708,7 +816,9 @@ var prefer_use_state_lazy_initialization_default = createRule({
708
816
  const hasNewCall = AST2__namespace.getNestedNewExpressions(useStateInput).some((n) => {
709
817
  return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
710
818
  });
711
- if (!hasFunctionCall && !hasNewCall) return;
819
+ if (!hasFunctionCall && !hasNewCall) {
820
+ return;
821
+ }
712
822
  context.report({
713
823
  messageId: "preferUseStateLazyInitialization",
714
824
  node: useStateInput
package/dist/index.mjs CHANGED
@@ -8,7 +8,7 @@ import { match, isMatching } from 'ts-pattern';
8
8
 
9
9
  // package.json
10
10
  var name = "eslint-plugin-react-hooks-extra";
11
- var version = "1.23.2";
11
+ var version = "1.23.3-beta.2";
12
12
  var createRule = createRuleForPlugin("hooks-extra");
13
13
  function isFromHookCall(name2, context, settings, predicate = F.constTrue) {
14
14
  const hookAlias = settings.additionalHooks?.[name2] ?? [];
@@ -23,7 +23,9 @@ function isFromHookCall(name2, context, settings, predicate = F.constTrue) {
23
23
  function isFromUseStateCall(context, settings) {
24
24
  const predicate = (topLevelId, call) => {
25
25
  const { parent } = call;
26
- if (!("id" in parent && parent.id?.type === AST_NODE_TYPES.ArrayPattern)) return true;
26
+ if (!("id" in parent && parent.id?.type === AST_NODE_TYPES.ArrayPattern)) {
27
+ return true;
28
+ }
27
29
  return parent.id.elements.findIndex((e) => e?.type === AST_NODE_TYPES.Identifier && e.name === topLevelId.name) === 1;
28
30
  };
29
31
  return isFromHookCall("useState", context, settings, predicate);
@@ -36,8 +38,12 @@ function isSetFunctionCall(context, settings) {
36
38
  // data.at(1)();
37
39
  case AST_NODE_TYPES.CallExpression: {
38
40
  const { callee } = node.callee;
39
- if (callee.type !== AST_NODE_TYPES.MemberExpression) return false;
40
- if (!("name" in callee.object)) return false;
41
+ if (callee.type !== AST_NODE_TYPES.MemberExpression) {
42
+ return false;
43
+ }
44
+ if (!("name" in callee.object)) {
45
+ return false;
46
+ }
41
47
  const isAt = isMatching({
42
48
  type: AST_NODE_TYPES.MemberExpression,
43
49
  property: {
@@ -46,7 +52,9 @@ function isSetFunctionCall(context, settings) {
46
52
  }
47
53
  }, callee);
48
54
  const [index] = node.callee.arguments;
49
- if (!isAt || !index) return false;
55
+ if (!isAt || !index) {
56
+ return false;
57
+ }
50
58
  const initialScope = context.sourceCode.getScope(node);
51
59
  return O.exists(VAR5.getStaticValue(index, initialScope), (v) => v === 1) && isIdFromUseStateCall(callee.object);
52
60
  }
@@ -58,7 +66,9 @@ function isSetFunctionCall(context, settings) {
58
66
  // const data = useState();
59
67
  // data[1]();
60
68
  case AST_NODE_TYPES.MemberExpression: {
61
- if (!("name" in node.callee.object)) return false;
69
+ if (!("name" in node.callee.object)) {
70
+ return false;
71
+ }
62
72
  const initialScope = context.sourceCode.getScope(node);
63
73
  return O.exists(VAR5.getStaticValue(node.callee.property, initialScope), (v) => v === 1) && isIdFromUseStateCall(node.callee.object);
64
74
  }
@@ -72,9 +82,15 @@ function isThenCall(node) {
72
82
  return node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "then";
73
83
  }
74
84
  function isVariableDeclaratorFromHookCall(node) {
75
- if (node.type !== AST_NODE_TYPES.VariableDeclarator) return false;
76
- if (node.id.type !== AST_NODE_TYPES.Identifier) return false;
77
- if (node.init?.type !== AST_NODE_TYPES.CallExpression) return false;
85
+ if (node.type !== AST_NODE_TYPES.VariableDeclarator) {
86
+ return false;
87
+ }
88
+ if (node.id.type !== AST_NODE_TYPES.Identifier) {
89
+ return false;
90
+ }
91
+ if (node.init?.type !== AST_NODE_TYPES.CallExpression) {
92
+ return false;
93
+ }
78
94
  switch (node.init.callee.type) {
79
95
  case AST_NODE_TYPES.Identifier:
80
96
  return isReactHookName(node.init.callee.name);
@@ -104,7 +120,9 @@ var no_direct_set_state_in_use_effect_default = createRule({
104
120
  },
105
121
  name: RULE_NAME,
106
122
  create(context) {
107
- if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
123
+ if (!/use\w*Effect/u.test(context.sourceCode.text)) {
124
+ return {};
125
+ }
108
126
  const settings = getSettingsFromContext(context);
109
127
  const additionalHooks = settings.additionalHooks ?? {};
110
128
  const isUseEffectLikeCall = isReactHookCallWithNameAlias("useEffect", context, additionalHooks.useEffect ?? []);
@@ -154,9 +172,13 @@ var no_direct_set_state_in_use_effect_default = createRule({
154
172
  CallExpression(node) {
155
173
  const setupFunction = O.getOrNull(setupFunctionRef.current);
156
174
  const pEntry = functionStack.at(-1);
157
- if (pEntry?.node.async) return;
175
+ if (pEntry?.node.async) {
176
+ return;
177
+ }
158
178
  match(getCallKind(node)).with("setState", () => {
159
- if (!pEntry) return;
179
+ if (!pEntry) {
180
+ return;
181
+ }
160
182
  switch (true) {
161
183
  case (pEntry.node === setupFunction || pEntry.kind === "immediate"): {
162
184
  context.report({
@@ -181,33 +203,51 @@ var no_direct_set_state_in_use_effect_default = createRule({
181
203
  }
182
204
  }
183
205
  }).with("useEffect", () => {
184
- if (AST2.isFunction(node.arguments.at(0))) return;
206
+ if (AST2.isFunction(node.arguments.at(0))) {
207
+ return;
208
+ }
185
209
  setupFunctionIdentifiers.push(...AST2.getNestedIdentifiers(node));
186
210
  }).with("other", () => {
187
- if (pEntry?.node !== setupFunction) return;
211
+ if (pEntry?.node !== setupFunction) {
212
+ return;
213
+ }
188
214
  indFunctionCalls.push(node);
189
215
  }).otherwise(F.constVoid);
190
216
  },
191
217
  Identifier(node) {
192
- if (node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) return;
193
- if (!isIdFromUseStateCall(node)) return;
218
+ if (node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) {
219
+ return;
220
+ }
221
+ if (!isIdFromUseStateCall(node)) {
222
+ return;
223
+ }
194
224
  switch (node.parent.type) {
195
225
  case AST_NODE_TYPES.ArrowFunctionExpression: {
196
226
  const parent = node.parent.parent;
197
- if (parent.type !== AST_NODE_TYPES.CallExpression) break;
198
- if (!isUseMemoCall2(parent)) break;
227
+ if (parent.type !== AST_NODE_TYPES.CallExpression) {
228
+ break;
229
+ }
230
+ if (!isUseMemoCall2(parent)) {
231
+ break;
232
+ }
199
233
  const mbVariableDeclarator = AST2.findParentNodeGuard(parent, isVariableDeclaratorFromHookCall);
200
- if (O.isNone(mbVariableDeclarator)) break;
234
+ if (O.isNone(mbVariableDeclarator)) {
235
+ break;
236
+ }
201
237
  const variableDeclarator = mbVariableDeclarator.value;
202
238
  const calls = indSetStateCallsInUseEffectArg0.get(variableDeclarator.init) ?? [];
203
239
  indSetStateCallsInUseEffectArg0.set(variableDeclarator.init, [...calls, node]);
204
240
  break;
205
241
  }
206
242
  case AST_NODE_TYPES.CallExpression: {
207
- if (node !== node.parent.arguments.at(0)) break;
243
+ if (node !== node.parent.arguments.at(0)) {
244
+ break;
245
+ }
208
246
  if (isUseCallbackCall2(node.parent)) {
209
247
  const mbVariableDeclarator = AST2.findParentNodeGuard(node.parent, isVariableDeclaratorFromHookCall);
210
- if (O.isNone(mbVariableDeclarator)) break;
248
+ if (O.isNone(mbVariableDeclarator)) {
249
+ break;
250
+ }
211
251
  const variableDeclarator = mbVariableDeclarator.value;
212
252
  const prevs = indSetStateCallsInUseEffectArg0.get(variableDeclarator.init) ?? [];
213
253
  indSetStateCallsInUseEffectArg0.set(variableDeclarator.init, [...prevs, node]);
@@ -243,7 +283,9 @@ var no_direct_set_state_in_use_effect_default = createRule({
243
283
  }
244
284
  }
245
285
  for (const { callee } of indFunctionCalls) {
246
- if (!("name" in callee)) continue;
286
+ if (!("name" in callee)) {
287
+ continue;
288
+ }
247
289
  const { name: name2 } = callee;
248
290
  const setStateCalls = getSetStateCalls(name2, context.sourceCode.getScope(callee));
249
291
  for (const setStateCall of setStateCalls) {
@@ -291,7 +333,9 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
291
333
  },
292
334
  name: RULE_NAME2,
293
335
  create(context) {
294
- if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
336
+ if (!/use\w*Effect/u.test(context.sourceCode.text)) {
337
+ return {};
338
+ }
295
339
  const settings = getSettingsFromContext(context);
296
340
  const additionalHooks = settings.additionalHooks ?? {};
297
341
  const isUseLayoutEffectLikeCall = isReactHookCallWithNameAlias(
@@ -345,9 +389,13 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
345
389
  CallExpression(node) {
346
390
  const setupFunction = O.getOrNull(setupFunctionRef.current);
347
391
  const pEntry = functionStack.at(-1);
348
- if (pEntry?.node.async) return;
392
+ if (pEntry?.node.async) {
393
+ return;
394
+ }
349
395
  match(getCallKind(node)).with("setState", () => {
350
- if (!pEntry) return;
396
+ if (!pEntry) {
397
+ return;
398
+ }
351
399
  switch (true) {
352
400
  case (pEntry.node === setupFunction || pEntry.kind === "immediate"): {
353
401
  context.report({
@@ -372,33 +420,51 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
372
420
  }
373
421
  }
374
422
  }).with("useLayoutEffect", () => {
375
- if (AST2.isFunction(node.arguments.at(0))) return;
423
+ if (AST2.isFunction(node.arguments.at(0))) {
424
+ return;
425
+ }
376
426
  setupFunctionIdentifiers.push(...AST2.getNestedIdentifiers(node));
377
427
  }).with("other", () => {
378
- if (pEntry?.node !== setupFunction) return;
428
+ if (pEntry?.node !== setupFunction) {
429
+ return;
430
+ }
379
431
  indFunctionCalls.push(node);
380
432
  }).otherwise(F.constVoid);
381
433
  },
382
434
  Identifier(node) {
383
- if (node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) return;
384
- if (!isIdFromUseStateCall(node)) return;
435
+ if (node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) {
436
+ return;
437
+ }
438
+ if (!isIdFromUseStateCall(node)) {
439
+ return;
440
+ }
385
441
  switch (node.parent.type) {
386
442
  case AST_NODE_TYPES.ArrowFunctionExpression: {
387
443
  const parent = node.parent.parent;
388
- if (parent.type !== AST_NODE_TYPES.CallExpression) break;
389
- if (!isUseMemoCall2(parent)) break;
444
+ if (parent.type !== AST_NODE_TYPES.CallExpression) {
445
+ break;
446
+ }
447
+ if (!isUseMemoCall2(parent)) {
448
+ break;
449
+ }
390
450
  const mbVariableDeclarator = AST2.findParentNodeGuard(parent, isVariableDeclaratorFromHookCall);
391
- if (O.isNone(mbVariableDeclarator)) break;
451
+ if (O.isNone(mbVariableDeclarator)) {
452
+ break;
453
+ }
392
454
  const variableDeclarator = mbVariableDeclarator.value;
393
455
  const calls = indSetStateCallsInUseLayoutEffectArg0.get(variableDeclarator.init) ?? [];
394
456
  indSetStateCallsInUseLayoutEffectArg0.set(variableDeclarator.init, [...calls, node]);
395
457
  break;
396
458
  }
397
459
  case AST_NODE_TYPES.CallExpression: {
398
- if (node !== node.parent.arguments.at(0)) break;
460
+ if (node !== node.parent.arguments.at(0)) {
461
+ break;
462
+ }
399
463
  if (isUseCallbackCall2(node.parent)) {
400
464
  const mbVariableDeclarator = AST2.findParentNodeGuard(node.parent, isVariableDeclaratorFromHookCall);
401
- if (O.isNone(mbVariableDeclarator)) break;
465
+ if (O.isNone(mbVariableDeclarator)) {
466
+ break;
467
+ }
402
468
  const variableDeclarator = mbVariableDeclarator.value;
403
469
  const prevs = indSetStateCallsInUseLayoutEffectArg0.get(variableDeclarator.init) ?? [];
404
470
  indSetStateCallsInUseLayoutEffectArg0.set(variableDeclarator.init, [...prevs, node]);
@@ -434,7 +500,9 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
434
500
  }
435
501
  }
436
502
  for (const { callee } of indFunctionCalls) {
437
- if (!("name" in callee)) continue;
503
+ if (!("name" in callee)) {
504
+ continue;
505
+ }
438
506
  const { name: name2 } = callee;
439
507
  const setStateCalls = getSetStateCalls(name2, context.sourceCode.getScope(callee));
440
508
  for (const setStateCall of setStateCalls) {
@@ -482,18 +550,28 @@ var no_unnecessary_use_callback_default = createRule({
482
550
  },
483
551
  name: RULE_NAME3,
484
552
  create(context) {
485
- if (!context.sourceCode.text.includes("use")) return {};
553
+ if (!context.sourceCode.text.includes("use")) {
554
+ return {};
555
+ }
486
556
  const alias = getSettingsFromContext(context).additionalHooks?.useCallback ?? [];
487
557
  return {
488
558
  CallExpression(node) {
489
- if (!isReactHookCall(node)) return;
559
+ if (!isReactHookCall(node)) {
560
+ return;
561
+ }
490
562
  const initialScope = context.sourceCode.getScope(node);
491
- if (!isUseCallbackCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) return;
563
+ if (!isUseCallbackCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) {
564
+ return;
565
+ }
492
566
  const scope = context.sourceCode.getScope(node);
493
567
  const component = scope.block;
494
- if (!AST2.isFunction(component)) return;
568
+ if (!AST2.isFunction(component)) {
569
+ return;
570
+ }
495
571
  const [arg0, arg1] = node.arguments;
496
- if (!arg0 || !arg1) return;
572
+ if (!arg0 || !arg1) {
573
+ return;
574
+ }
497
575
  const hasEmptyDeps = F.pipe(
498
576
  match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
499
577
  return F.pipe(
@@ -504,7 +582,9 @@ var no_unnecessary_use_callback_default = createRule({
504
582
  }).otherwise(O.none),
505
583
  O.exists((x) => x.elements.length === 0)
506
584
  );
507
- if (!hasEmptyDeps) return;
585
+ if (!hasEmptyDeps) {
586
+ return;
587
+ }
508
588
  const isReferencedToComponentScope = F.pipe(
509
589
  match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
510
590
  if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) {
@@ -551,24 +631,36 @@ var no_unnecessary_use_memo_default = createRule({
551
631
  },
552
632
  name: RULE_NAME4,
553
633
  create(context) {
554
- if (!context.sourceCode.text.includes("use")) return {};
634
+ if (!context.sourceCode.text.includes("use")) {
635
+ return {};
636
+ }
555
637
  const alias = getSettingsFromContext(context).additionalHooks?.useMemo ?? [];
556
638
  return {
557
639
  CallExpression(node) {
558
- if (!isReactHookCall(node)) return;
640
+ if (!isReactHookCall(node)) {
641
+ return;
642
+ }
559
643
  const initialScope = context.sourceCode.getScope(node);
560
- if (!isUseMemoCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) return;
644
+ if (!isUseMemoCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) {
645
+ return;
646
+ }
561
647
  const scope = context.sourceCode.getScope(node);
562
648
  const component = scope.block;
563
- if (!AST2.isFunction(component)) return;
649
+ if (!AST2.isFunction(component)) {
650
+ return;
651
+ }
564
652
  const [arg0, arg1] = node.arguments;
565
- if (!arg0 || !arg1) return;
653
+ if (!arg0 || !arg1) {
654
+ return;
655
+ }
566
656
  const hasCallInArg0 = F.pipe(
567
657
  O.some(arg0),
568
658
  O.filter((n) => AST2.isFunction(n)),
569
659
  O.exists((n) => [...AST2.getNestedCallExpressions(n.body), ...AST2.getNestedNewExpressions(n.body)].length > 0)
570
660
  );
571
- if (hasCallInArg0) return;
661
+ if (hasCallInArg0) {
662
+ return;
663
+ }
572
664
  const hasEmptyDeps = F.pipe(
573
665
  match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
574
666
  return F.pipe(
@@ -579,7 +671,9 @@ var no_unnecessary_use_memo_default = createRule({
579
671
  }).otherwise(O.none),
580
672
  O.exists((x) => x.elements.length === 0)
581
673
  );
582
- if (!hasEmptyDeps) return;
674
+ if (!hasEmptyDeps) {
675
+ return;
676
+ }
583
677
  const isReferencedToComponentScope = F.pipe(
584
678
  match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
585
679
  if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) {
@@ -635,9 +729,15 @@ var no_useless_custom_hooks_default = createRule({
635
729
  "Program:exit"(node) {
636
730
  const allHooks = ctx.getAllHooks(node);
637
731
  for (const { name: name2, node: node2, hookCalls } of allHooks.values()) {
638
- if (AST2.isEmptyFunction(node2)) continue;
639
- if (hookCalls.length > 0) continue;
640
- if (isNodeContainsUseCallComments(node2, context)) continue;
732
+ if (AST2.isEmptyFunction(node2)) {
733
+ continue;
734
+ }
735
+ if (hookCalls.length > 0) {
736
+ continue;
737
+ }
738
+ if (isNodeContainsUseCallComments(node2, context)) {
739
+ continue;
740
+ }
641
741
  context.report({
642
742
  messageId: "noUselessCustomHooks",
643
743
  node: node2,
@@ -670,14 +770,22 @@ var prefer_use_state_lazy_initialization_default = createRule({
670
770
  },
671
771
  name: RULE_NAME6,
672
772
  create(context) {
673
- if (!context.sourceCode.text.includes("use")) return {};
773
+ if (!context.sourceCode.text.includes("use")) {
774
+ return {};
775
+ }
674
776
  const alias = getSettingsFromContext(context).additionalHooks?.useState ?? [];
675
777
  return {
676
778
  CallExpression(node) {
677
- if (!isReactHookCall(node)) return;
678
- if (!isUseStateCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) return;
779
+ if (!isReactHookCall(node)) {
780
+ return;
781
+ }
782
+ if (!isUseStateCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) {
783
+ return;
784
+ }
679
785
  const [useStateInput] = node.arguments;
680
- if (!useStateInput) return;
786
+ if (!useStateInput) {
787
+ return;
788
+ }
681
789
  const nestedCallExpressions = AST2.getNestedCallExpressions(useStateInput);
682
790
  const hasFunctionCall = nestedCallExpressions.some((n) => {
683
791
  return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
@@ -685,7 +793,9 @@ var prefer_use_state_lazy_initialization_default = createRule({
685
793
  const hasNewCall = AST2.getNestedNewExpressions(useStateInput).some((n) => {
686
794
  return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
687
795
  });
688
- if (!hasFunctionCall && !hasNewCall) return;
796
+ if (!hasFunctionCall && !hasNewCall) {
797
+ return;
798
+ }
689
799
  context.report({
690
800
  messageId: "preferUseStateLazyInitialization",
691
801
  node: useStateInput
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-hooks-extra",
3
- "version": "1.23.2",
3
+ "version": "1.23.3-beta.2",
4
4
  "description": "ESLint React's ESLint plugin for React Hooks related rules.",
5
5
  "keywords": [
6
6
  "react",
@@ -22,6 +22,7 @@
22
22
  },
23
23
  "license": "MIT",
24
24
  "author": "Eva1ent<rel1cx@proton.me>",
25
+ "sideEffects": false,
25
26
  "exports": {
26
27
  ".": {
27
28
  "import": {
@@ -36,6 +37,7 @@
36
37
  "./package.json": "./package.json"
37
38
  },
38
39
  "main": "dist/index.js",
40
+ "module": "dist/index.mjs",
39
41
  "types": "dist/index.d.ts",
40
42
  "files": [
41
43
  "dist",
@@ -48,13 +50,13 @@
48
50
  "@typescript-eslint/utils": "^8.19.1",
49
51
  "string-ts": "^2.2.0",
50
52
  "ts-pattern": "^5.6.0",
51
- "@eslint-react/ast": "1.23.2",
52
- "@eslint-react/core": "1.23.2",
53
- "@eslint-react/eff": "1.23.2",
54
- "@eslint-react/jsx": "1.23.2",
55
- "@eslint-react/shared": "1.23.2",
56
- "@eslint-react/types": "1.23.2",
57
- "@eslint-react/var": "1.23.2"
53
+ "@eslint-react/eff": "1.23.3-beta.2",
54
+ "@eslint-react/ast": "1.23.3-beta.2",
55
+ "@eslint-react/jsx": "1.23.3-beta.2",
56
+ "@eslint-react/var": "1.23.3-beta.2",
57
+ "@eslint-react/shared": "1.23.3-beta.2",
58
+ "@eslint-react/types": "1.23.3-beta.2",
59
+ "@eslint-react/core": "1.23.3-beta.2"
58
60
  },
59
61
  "devDependencies": {
60
62
  "@types/react": "^19.0.3",
@@ -81,8 +83,6 @@
81
83
  "publishConfig": {
82
84
  "access": "public"
83
85
  },
84
- "sideEffects": false,
85
- "module": "dist/index.mjs",
86
86
  "scripts": {
87
87
  "build": "tsup --dts-resolve",
88
88
  "lint:publish": "publint",