eslint-plugin-react-hooks-extra 1.23.3-next.7 → 1.24.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.
Files changed (3) hide show
  1. package/dist/index.js +140 -136
  2. package/dist/index.mjs +140 -136
  3. package/package.json +11 -11
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var AST2 = require('@eslint-react/ast');
3
+ var AST = require('@eslint-react/ast');
4
4
  var core = require('@eslint-react/core');
5
5
  var eff = require('@eslint-react/eff');
6
6
  var shared = require('@eslint-react/shared');
@@ -26,22 +26,23 @@ function _interopNamespace(e) {
26
26
  return Object.freeze(n);
27
27
  }
28
28
 
29
- var AST2__namespace = /*#__PURE__*/_interopNamespace(AST2);
29
+ var AST__namespace = /*#__PURE__*/_interopNamespace(AST);
30
30
  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.3-next.7";
34
+ var version = "1.24.0-beta.0";
35
35
  var createRule = shared.createRuleForPlugin("hooks-extra");
36
- function isFromHookCall(name2, context, settings, predicate = eff.F.constTrue) {
36
+ function isFromHookCall(name2, context, settings, predicate = eff.returnTrue) {
37
37
  const hookAlias = settings.additionalHooks?.[name2] ?? [];
38
- return (topLevelId) => eff.F.pipe(
39
- VAR5__namespace.findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
40
- eff.O.flatMap(VAR5__namespace.getVariableNode(0)),
41
- eff.O.filter(AST2__namespace.is(types.AST_NODE_TYPES.CallExpression)),
42
- eff.O.filter(core.isReactHookCallWithNameAlias(name2, context, hookAlias)),
43
- eff.O.exists((call) => predicate(topLevelId, call))
44
- );
38
+ return (topLevelId) => {
39
+ const variable = VAR5__namespace.findVariable(topLevelId, context.sourceCode.getScope(topLevelId));
40
+ const variableNode = VAR5__namespace.getVariableNode(variable, 0);
41
+ if (variableNode == null) return false;
42
+ if (variableNode.type !== types.AST_NODE_TYPES.CallExpression) return false;
43
+ if (!core.isReactHookCallWithNameAlias(name2, context, hookAlias)(variableNode)) return false;
44
+ return predicate(topLevelId, variableNode);
45
+ };
45
46
  }
46
47
  function isFromUseStateCall(context, settings) {
47
48
  const predicate = (topLevelId, call) => {
@@ -72,8 +73,13 @@ function isSetFunctionCall(context, settings) {
72
73
  if (!isAt || index == null) {
73
74
  return false;
74
75
  }
75
- const initialScope = context.sourceCode.getScope(node);
76
- return eff.O.exists(VAR5__namespace.getStaticValue(index, initialScope), (v) => v === 1) && isIdFromUseStateCall(callee.object);
76
+ const indexScope = context.sourceCode.getScope(node);
77
+ const indexValue = VAR5__namespace.toResolved({
78
+ kind: "lazy",
79
+ node: index,
80
+ initialScope: indexScope
81
+ }).value;
82
+ return indexValue === 1 && isIdFromUseStateCall(callee.object);
77
83
  }
78
84
  // const [data, setData] = useState();
79
85
  // setData();
@@ -86,8 +92,14 @@ function isSetFunctionCall(context, settings) {
86
92
  if (!("name" in node.callee.object)) {
87
93
  return false;
88
94
  }
89
- const initialScope = context.sourceCode.getScope(node);
90
- return eff.O.exists(VAR5__namespace.getStaticValue(node.callee.property, initialScope), (v) => v === 1) && isIdFromUseStateCall(node.callee.object);
95
+ const property = node.callee.property;
96
+ const propertyScope = context.sourceCode.getScope(node);
97
+ const propertyValue = VAR5__namespace.toResolved({
98
+ kind: "lazy",
99
+ node: property,
100
+ initialScope: propertyScope
101
+ }).value;
102
+ return propertyValue === 1 && isIdFromUseStateCall(node.callee.object);
91
103
  }
92
104
  default: {
93
105
  return false;
@@ -148,8 +160,8 @@ var no_direct_set_state_in_use_effect_default = createRule({
148
160
  const isUseCallbackCall2 = core.isReactHookCallWithNameAlias("useCallback", context, additionalHooks.useCallback ?? []);
149
161
  const isSetStateCall = isSetFunctionCall(context, settings);
150
162
  const isIdFromUseStateCall = isFromUseStateCall(context, settings);
151
- const functionStack = [];
152
- const setupFunctionRef = { current: eff.O.none() };
163
+ const functionEntries = [];
164
+ const setupFunctionRef = { current: null };
153
165
  const setupFunctionIdentifiers = [];
154
166
  const indFunctionCalls = [];
155
167
  const indSetStateCalls = /* @__PURE__ */ new WeakMap();
@@ -157,10 +169,12 @@ var no_direct_set_state_in_use_effect_default = createRule({
157
169
  const indSetStateCallsInUseEffectSetup = /* @__PURE__ */ new Map();
158
170
  const indSetStateCallsInUseMemoOrCallback = /* @__PURE__ */ new WeakMap();
159
171
  const onSetupFunctionEnter = (node) => {
160
- setupFunctionRef.current = eff.O.some(node);
172
+ setupFunctionRef.current = node;
161
173
  };
162
174
  const onSetupFunctionExit = (node) => {
163
- setupFunctionRef.current = eff.O.filter(setupFunctionRef.current, (current) => current !== node);
175
+ if (setupFunctionRef.current === node) {
176
+ setupFunctionRef.current = null;
177
+ }
164
178
  };
165
179
  function isSetupFunction(node) {
166
180
  return node.parent?.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee !== node && isUseEffectLikeCall(node.parent);
@@ -169,26 +183,26 @@ var no_direct_set_state_in_use_effect_default = createRule({
169
183
  return tsPattern.match(node).when(isUseStateCall2, () => "useState").when(isUseEffectLikeCall, () => "useEffect").when(isSetStateCall, () => "setState").when(isThenCall, () => "then").otherwise(() => "other");
170
184
  }
171
185
  function getFunctionKind(node) {
172
- return tsPattern.match(node).when(isSetupFunction, () => "setup").when(AST2__namespace.isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
186
+ return tsPattern.match(node).when(isSetupFunction, () => "setup").when(AST__namespace.isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
173
187
  }
174
188
  return {
175
189
  ":function"(node) {
176
190
  const kind = getFunctionKind(node);
177
- functionStack.push({ kind, node });
191
+ functionEntries.push({ kind, node });
178
192
  if (kind === "setup") {
179
193
  onSetupFunctionEnter(node);
180
194
  }
181
195
  },
182
196
  ":function:exit"(node) {
183
- const { kind } = functionStack.at(-1) ?? {};
197
+ const { kind } = functionEntries.at(-1) ?? {};
184
198
  if (kind === "setup") {
185
199
  onSetupFunctionExit(node);
186
200
  }
187
- functionStack.pop();
201
+ functionEntries.pop();
188
202
  },
189
203
  CallExpression(node) {
190
- const setupFunction = eff.O.getOrNull(setupFunctionRef.current);
191
- const pEntry = functionStack.at(-1);
204
+ const setupFunction = setupFunctionRef.current;
205
+ const pEntry = functionEntries.at(-1);
192
206
  if (pEntry?.node.async) {
193
207
  return;
194
208
  }
@@ -208,28 +222,28 @@ var no_direct_set_state_in_use_effect_default = createRule({
208
222
  return;
209
223
  }
210
224
  default: {
211
- const mbVariableDeclarator = AST2__namespace.findParentNodeGuard(node, isVariableDeclaratorFromHookCall);
212
- if (eff.O.isNone(mbVariableDeclarator)) {
225
+ const variableDeclarator = AST__namespace.findParentNodeGuard(node, isVariableDeclaratorFromHookCall);
226
+ if (variableDeclarator === eff._) {
213
227
  const calls = indSetStateCalls.get(pEntry.node) ?? [];
214
228
  indSetStateCalls.set(pEntry.node, [...calls, node]);
215
229
  return;
216
230
  }
217
- const vd = mbVariableDeclarator.value;
218
- const prevs = indSetStateCallsInUseMemoOrCallback.get(vd.init) ?? [];
219
- indSetStateCallsInUseMemoOrCallback.set(vd.init, [...prevs, node]);
231
+ const init = variableDeclarator.init;
232
+ const prevs = indSetStateCallsInUseMemoOrCallback.get(init) ?? [];
233
+ indSetStateCallsInUseMemoOrCallback.set(init, [...prevs, node]);
220
234
  }
221
235
  }
222
236
  }).with("useEffect", () => {
223
- if (AST2__namespace.isFunction(node.arguments.at(0))) {
237
+ if (AST__namespace.isFunction(node.arguments.at(0))) {
224
238
  return;
225
239
  }
226
- setupFunctionIdentifiers.push(...AST2__namespace.getNestedIdentifiers(node));
240
+ setupFunctionIdentifiers.push(...AST__namespace.getNestedIdentifiers(node));
227
241
  }).with("other", () => {
228
242
  if (pEntry?.node !== setupFunction) {
229
243
  return;
230
244
  }
231
245
  indFunctionCalls.push(node);
232
- }).otherwise(eff.F.constVoid);
246
+ }).otherwise(() => eff._);
233
247
  },
234
248
  Identifier(node) {
235
249
  if (node.parent.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee === node) {
@@ -247,11 +261,10 @@ var no_direct_set_state_in_use_effect_default = createRule({
247
261
  if (!isUseMemoCall2(parent)) {
248
262
  break;
249
263
  }
250
- const mbVariableDeclarator = AST2__namespace.findParentNodeGuard(parent, isVariableDeclaratorFromHookCall);
251
- if (eff.O.isNone(mbVariableDeclarator)) {
264
+ const variableDeclarator = AST__namespace.findParentNodeGuard(parent, isVariableDeclaratorFromHookCall);
265
+ if (variableDeclarator == null) {
252
266
  break;
253
267
  }
254
- const variableDeclarator = mbVariableDeclarator.value;
255
268
  const calls = indSetStateCallsInUseEffectArg0.get(variableDeclarator.init) ?? [];
256
269
  indSetStateCallsInUseEffectArg0.set(variableDeclarator.init, [...calls, node]);
257
270
  break;
@@ -261,11 +274,10 @@ var no_direct_set_state_in_use_effect_default = createRule({
261
274
  break;
262
275
  }
263
276
  if (isUseCallbackCall2(node.parent)) {
264
- const mbVariableDeclarator = AST2__namespace.findParentNodeGuard(node.parent, isVariableDeclaratorFromHookCall);
265
- if (eff.O.isNone(mbVariableDeclarator)) {
277
+ const variableDeclarator = AST__namespace.findParentNodeGuard(node.parent, isVariableDeclaratorFromHookCall);
278
+ if (variableDeclarator == null) {
266
279
  break;
267
280
  }
268
- const variableDeclarator = mbVariableDeclarator.value;
269
281
  const prevs = indSetStateCallsInUseEffectArg0.get(variableDeclarator.init) ?? [];
270
282
  indSetStateCallsInUseEffectArg0.set(variableDeclarator.init, [...prevs, node]);
271
283
  }
@@ -279,7 +291,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
279
291
  },
280
292
  "Program:exit"() {
281
293
  const getSetStateCalls = (id, initialScope) => {
282
- const node = eff.O.flatMap(VAR5__namespace.findVariable(id, initialScope), VAR5__namespace.getVariableNode(0)).pipe(eff.O.getOrNull);
294
+ const node = VAR5__namespace.getVariableNode(VAR5__namespace.findVariable(id, initialScope), 0);
283
295
  switch (node?.type) {
284
296
  case types.AST_NODE_TYPES.ArrowFunctionExpression:
285
297
  case types.AST_NODE_TYPES.FunctionDeclaration:
@@ -290,7 +302,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
290
302
  }
291
303
  return [];
292
304
  };
293
- for (const [_, calls] of indSetStateCallsInUseEffectSetup) {
305
+ for (const [, calls] of indSetStateCallsInUseEffectSetup) {
294
306
  for (const call of calls) {
295
307
  context.report({
296
308
  messageId: "noDirectSetStateInUseEffect",
@@ -310,7 +322,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
310
322
  messageId: "noDirectSetStateInUseEffect",
311
323
  node: setStateCall,
312
324
  data: {
313
- name: AST2__namespace.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
325
+ name: AST__namespace.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
314
326
  }
315
327
  });
316
328
  }
@@ -322,7 +334,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
322
334
  messageId: "noDirectSetStateInUseEffect",
323
335
  node: setStateCall,
324
336
  data: {
325
- name: AST2__namespace.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
337
+ name: AST__namespace.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
326
338
  }
327
339
  });
328
340
  }
@@ -365,8 +377,8 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
365
377
  const isUseCallbackCall2 = core.isReactHookCallWithNameAlias("useCallback", context, additionalHooks.useCallback ?? []);
366
378
  const isSetStateCall = isSetFunctionCall(context, settings);
367
379
  const isIdFromUseStateCall = isFromUseStateCall(context, settings);
368
- const functionStack = [];
369
- const setupFunctionRef = { current: eff.O.none() };
380
+ const functionEntries = [];
381
+ const setupFunctionRef = { current: null };
370
382
  const setupFunctionIdentifiers = [];
371
383
  const indFunctionCalls = [];
372
384
  const indSetStateCalls = /* @__PURE__ */ new WeakMap();
@@ -374,10 +386,12 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
374
386
  const indSetStateCallsInUseLayoutEffectSetup = /* @__PURE__ */ new Map();
375
387
  const indSetStateCallsInUseMemoOrCallback = /* @__PURE__ */ new WeakMap();
376
388
  const onSetupFunctionEnter = (node) => {
377
- setupFunctionRef.current = eff.O.some(node);
389
+ setupFunctionRef.current = node;
378
390
  };
379
391
  const onSetupFunctionExit = (node) => {
380
- setupFunctionRef.current = eff.O.filter(setupFunctionRef.current, (current) => current !== node);
392
+ if (setupFunctionRef.current === node) {
393
+ setupFunctionRef.current = null;
394
+ }
381
395
  };
382
396
  function isSetupFunction(node) {
383
397
  return node.parent?.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee !== node && isUseLayoutEffectLikeCall(node.parent);
@@ -386,26 +400,26 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
386
400
  return tsPattern.match(node).when(isUseStateCall2, () => "useState").when(isUseLayoutEffectLikeCall, () => "useLayoutEffect").when(isSetStateCall, () => "setState").when(isThenCall, () => "then").otherwise(() => "other");
387
401
  }
388
402
  function getFunctionKind(node) {
389
- return tsPattern.match(node).when(isSetupFunction, () => "setup").when(AST2__namespace.isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
403
+ return tsPattern.match(node).when(isSetupFunction, () => "setup").when(AST__namespace.isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
390
404
  }
391
405
  return {
392
406
  ":function"(node) {
393
407
  const kind = getFunctionKind(node);
394
- functionStack.push({ kind, node });
408
+ functionEntries.push({ kind, node });
395
409
  if (kind === "setup") {
396
410
  onSetupFunctionEnter(node);
397
411
  }
398
412
  },
399
413
  ":function:exit"(node) {
400
- const { kind } = functionStack.at(-1) ?? {};
414
+ const { kind } = functionEntries.at(-1) ?? {};
401
415
  if (kind === "setup") {
402
416
  onSetupFunctionExit(node);
403
417
  }
404
- functionStack.pop();
418
+ functionEntries.pop();
405
419
  },
406
420
  CallExpression(node) {
407
- const setupFunction = eff.O.getOrNull(setupFunctionRef.current);
408
- const pEntry = functionStack.at(-1);
421
+ const setupFunction = setupFunctionRef.current;
422
+ const pEntry = functionEntries.at(-1);
409
423
  if (pEntry?.node.async) {
410
424
  return;
411
425
  }
@@ -425,28 +439,28 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
425
439
  return;
426
440
  }
427
441
  default: {
428
- const mbVariableDeclarator = AST2__namespace.findParentNodeGuard(node, isVariableDeclaratorFromHookCall);
429
- if (eff.O.isNone(mbVariableDeclarator)) {
442
+ const variableDeclarator = AST__namespace.findParentNodeGuard(node, isVariableDeclaratorFromHookCall);
443
+ if (variableDeclarator === eff._) {
430
444
  const calls = indSetStateCalls.get(pEntry.node) ?? [];
431
445
  indSetStateCalls.set(pEntry.node, [...calls, node]);
432
446
  return;
433
447
  }
434
- const vd = mbVariableDeclarator.value;
435
- const prevs = indSetStateCallsInUseMemoOrCallback.get(vd.init) ?? [];
436
- indSetStateCallsInUseMemoOrCallback.set(vd.init, [...prevs, node]);
448
+ const init = variableDeclarator.init;
449
+ const prevs = indSetStateCallsInUseMemoOrCallback.get(init) ?? [];
450
+ indSetStateCallsInUseMemoOrCallback.set(init, [...prevs, node]);
437
451
  }
438
452
  }
439
453
  }).with("useLayoutEffect", () => {
440
- if (AST2__namespace.isFunction(node.arguments.at(0))) {
454
+ if (AST__namespace.isFunction(node.arguments.at(0))) {
441
455
  return;
442
456
  }
443
- setupFunctionIdentifiers.push(...AST2__namespace.getNestedIdentifiers(node));
457
+ setupFunctionIdentifiers.push(...AST__namespace.getNestedIdentifiers(node));
444
458
  }).with("other", () => {
445
459
  if (pEntry?.node !== setupFunction) {
446
460
  return;
447
461
  }
448
462
  indFunctionCalls.push(node);
449
- }).otherwise(eff.F.constVoid);
463
+ }).otherwise(() => eff._);
450
464
  },
451
465
  Identifier(node) {
452
466
  if (node.parent.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee === node) {
@@ -464,11 +478,10 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
464
478
  if (!isUseMemoCall2(parent)) {
465
479
  break;
466
480
  }
467
- const mbVariableDeclarator = AST2__namespace.findParentNodeGuard(parent, isVariableDeclaratorFromHookCall);
468
- if (eff.O.isNone(mbVariableDeclarator)) {
481
+ const variableDeclarator = AST__namespace.findParentNodeGuard(parent, isVariableDeclaratorFromHookCall);
482
+ if (variableDeclarator == null) {
469
483
  break;
470
484
  }
471
- const variableDeclarator = mbVariableDeclarator.value;
472
485
  const calls = indSetStateCallsInUseLayoutEffectArg0.get(variableDeclarator.init) ?? [];
473
486
  indSetStateCallsInUseLayoutEffectArg0.set(variableDeclarator.init, [...calls, node]);
474
487
  break;
@@ -478,11 +491,10 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
478
491
  break;
479
492
  }
480
493
  if (isUseCallbackCall2(node.parent)) {
481
- const mbVariableDeclarator = AST2__namespace.findParentNodeGuard(node.parent, isVariableDeclaratorFromHookCall);
482
- if (eff.O.isNone(mbVariableDeclarator)) {
494
+ const variableDeclarator = AST__namespace.findParentNodeGuard(node.parent, isVariableDeclaratorFromHookCall);
495
+ if (variableDeclarator == null) {
483
496
  break;
484
497
  }
485
- const variableDeclarator = mbVariableDeclarator.value;
486
498
  const prevs = indSetStateCallsInUseLayoutEffectArg0.get(variableDeclarator.init) ?? [];
487
499
  indSetStateCallsInUseLayoutEffectArg0.set(variableDeclarator.init, [...prevs, node]);
488
500
  }
@@ -496,7 +508,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
496
508
  },
497
509
  "Program:exit"() {
498
510
  const getSetStateCalls = (id, initialScope) => {
499
- const node = eff.O.flatMap(VAR5__namespace.findVariable(id, initialScope), VAR5__namespace.getVariableNode(0)).pipe(eff.O.getOrNull);
511
+ const node = VAR5__namespace.getVariableNode(VAR5__namespace.findVariable(id, initialScope), 0);
500
512
  switch (node?.type) {
501
513
  case types.AST_NODE_TYPES.ArrowFunctionExpression:
502
514
  case types.AST_NODE_TYPES.FunctionDeclaration:
@@ -507,7 +519,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
507
519
  }
508
520
  return [];
509
521
  };
510
- for (const [_, calls] of indSetStateCallsInUseLayoutEffectSetup) {
522
+ for (const [, calls] of indSetStateCallsInUseLayoutEffectSetup) {
511
523
  for (const call of calls) {
512
524
  context.report({
513
525
  messageId: "noDirectSetStateInUseLayoutEffect",
@@ -527,7 +539,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
527
539
  messageId: "noDirectSetStateInUseLayoutEffect",
528
540
  node: setStateCall,
529
541
  data: {
530
- name: AST2__namespace.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
542
+ name: AST__namespace.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
531
543
  }
532
544
  });
533
545
  }
@@ -539,7 +551,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
539
551
  messageId: "noDirectSetStateInUseLayoutEffect",
540
552
  node: setStateCall,
541
553
  data: {
542
- name: AST2__namespace.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
554
+ name: AST__namespace.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
543
555
  }
544
556
  });
545
557
  }
@@ -582,43 +594,41 @@ var no_unnecessary_use_callback_default = createRule({
582
594
  }
583
595
  const scope = context.sourceCode.getScope(node);
584
596
  const component = scope.block;
585
- if (!AST2__namespace.isFunction(component)) {
597
+ if (!AST__namespace.isFunction(component)) {
586
598
  return;
587
599
  }
588
600
  const [arg0, arg1] = node.arguments;
589
601
  if (arg0 == null || arg1 == null) {
590
602
  return;
591
603
  }
592
- const hasEmptyDeps = eff.F.pipe(
593
- tsPattern.match(arg1).with({ type: types.AST_NODE_TYPES.ArrayExpression }, eff.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
594
- return eff.F.pipe(
595
- VAR5__namespace.findVariable(n.name, initialScope),
596
- eff.O.flatMap(VAR5__namespace.getVariableNode(0)),
597
- eff.O.filter(AST2__namespace.is(types.AST_NODE_TYPES.ArrayExpression))
598
- );
599
- }).otherwise(eff.O.none),
600
- eff.O.exists((x) => x.elements.length === 0)
601
- );
604
+ const hasEmptyDeps = tsPattern.match(arg1).with({ type: types.AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
605
+ const variable = VAR5__namespace.findVariable(n.name, initialScope);
606
+ const variableNode = VAR5__namespace.getVariableNode(variable, 0);
607
+ if (variableNode?.type !== types.AST_NODE_TYPES.ArrayExpression) {
608
+ return false;
609
+ }
610
+ return variableNode.elements.length === 0;
611
+ }).otherwise(() => false);
602
612
  if (!hasEmptyDeps) {
603
613
  return;
604
614
  }
605
- const isReferencedToComponentScope = eff.F.pipe(
606
- tsPattern.match(arg0).with({ type: types.AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
607
- if (n.body.type === types.AST_NODE_TYPES.ArrowFunctionExpression) {
608
- return eff.O.some(n.body);
609
- }
610
- return eff.O.some(n);
611
- }).with({ type: types.AST_NODE_TYPES.FunctionExpression }, eff.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
612
- return eff.F.pipe(
613
- VAR5__namespace.findVariable(n.name, initialScope),
614
- eff.O.flatMap(VAR5__namespace.getVariableNode(0)),
615
- eff.O.filter(AST2__namespace.isFunction)
616
- );
617
- }).otherwise(eff.O.none),
618
- eff.O.map((n) => context.sourceCode.getScope(n)),
619
- eff.O.map((s) => VAR5__namespace.getChidScopes(s).flatMap((x) => x.references)),
620
- eff.O.exists((refs) => refs.some((x) => x.resolved?.scope.block === component))
621
- );
615
+ const arg0Node = tsPattern.match(arg0).with({ type: types.AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
616
+ if (n.body.type === types.AST_NODE_TYPES.ArrowFunctionExpression) {
617
+ return n.body;
618
+ }
619
+ return n;
620
+ }).with({ type: types.AST_NODE_TYPES.FunctionExpression }, eff.identity).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
621
+ const variable = VAR5__namespace.findVariable(n.name, initialScope);
622
+ const variableNode = VAR5__namespace.getVariableNode(variable, 0);
623
+ if (variableNode?.type !== types.AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== types.AST_NODE_TYPES.FunctionExpression) {
624
+ return eff._;
625
+ }
626
+ return variableNode;
627
+ }).otherwise(() => eff._);
628
+ if (arg0Node === eff._) return;
629
+ const arg0NodeScope = context.sourceCode.getScope(arg0Node);
630
+ const arg0NodeReferences = VAR5__namespace.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
631
+ const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
622
632
  if (!isReferencedToComponentScope) {
623
633
  context.report({
624
634
  messageId: "noUnnecessaryUseCallback",
@@ -663,51 +673,45 @@ var no_unnecessary_use_memo_default = createRule({
663
673
  }
664
674
  const scope = context.sourceCode.getScope(node);
665
675
  const component = scope.block;
666
- if (!AST2__namespace.isFunction(component)) {
676
+ if (!AST__namespace.isFunction(component)) {
667
677
  return;
668
678
  }
669
679
  const [arg0, arg1] = node.arguments;
670
680
  if (arg0 == null || arg1 == null) {
671
681
  return;
672
682
  }
673
- const hasCallInArg0 = eff.F.pipe(
674
- eff.O.some(arg0),
675
- eff.O.filter((n) => AST2__namespace.isFunction(n)),
676
- eff.O.exists((n) => [...AST2__namespace.getNestedCallExpressions(n.body), ...AST2__namespace.getNestedNewExpressions(n.body)].length > 0)
677
- );
683
+ const hasCallInArg0 = AST__namespace.isFunction(arg0) && [...AST__namespace.getNestedCallExpressions(arg0.body), ...AST__namespace.getNestedNewExpressions(arg0.body)].length > 0;
678
684
  if (hasCallInArg0) {
679
685
  return;
680
686
  }
681
- const hasEmptyDeps = eff.F.pipe(
682
- tsPattern.match(arg1).with({ type: types.AST_NODE_TYPES.ArrayExpression }, eff.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
683
- return eff.F.pipe(
684
- VAR5__namespace.findVariable(n.name, initialScope),
685
- eff.O.flatMap(VAR5__namespace.getVariableNode(0)),
686
- eff.O.filter(AST2__namespace.is(types.AST_NODE_TYPES.ArrayExpression))
687
- );
688
- }).otherwise(eff.O.none),
689
- eff.O.exists((x) => x.elements.length === 0)
690
- );
687
+ const hasEmptyDeps = tsPattern.match(arg1).with({ type: types.AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
688
+ const variable = VAR5__namespace.findVariable(n.name, initialScope);
689
+ const variableNode = VAR5__namespace.getVariableNode(variable, 0);
690
+ if (variableNode?.type !== types.AST_NODE_TYPES.ArrayExpression) {
691
+ return false;
692
+ }
693
+ return variableNode.elements.length === 0;
694
+ }).otherwise(() => false);
691
695
  if (!hasEmptyDeps) {
692
696
  return;
693
697
  }
694
- const isReferencedToComponentScope = eff.F.pipe(
695
- tsPattern.match(arg0).with({ type: types.AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
696
- if (n.body.type === types.AST_NODE_TYPES.ArrowFunctionExpression) {
697
- return eff.O.some(n.body);
698
- }
699
- return eff.O.some(n);
700
- }).with({ type: types.AST_NODE_TYPES.FunctionExpression }, eff.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
701
- return eff.F.pipe(
702
- VAR5__namespace.findVariable(n.name, initialScope),
703
- eff.O.flatMap(VAR5__namespace.getVariableNode(0)),
704
- eff.O.filter(AST2__namespace.isFunction)
705
- );
706
- }).otherwise(eff.O.none),
707
- eff.O.map((n) => context.sourceCode.getScope(n)),
708
- eff.O.map((s) => VAR5__namespace.getChidScopes(s).flatMap((x) => x.references)),
709
- eff.O.exists((refs) => refs.some((x) => x.resolved?.scope.block === component))
710
- );
698
+ const arg0Node = tsPattern.match(arg0).with({ type: types.AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
699
+ if (n.body.type === types.AST_NODE_TYPES.ArrowFunctionExpression) {
700
+ return n.body;
701
+ }
702
+ return n;
703
+ }).with({ type: types.AST_NODE_TYPES.FunctionExpression }, eff.identity).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
704
+ const variable = VAR5__namespace.findVariable(n.name, initialScope);
705
+ const variableNode = VAR5__namespace.getVariableNode(variable, 0);
706
+ if (variableNode?.type !== types.AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== types.AST_NODE_TYPES.FunctionExpression) {
707
+ return eff._;
708
+ }
709
+ return variableNode;
710
+ }).otherwise(() => eff._);
711
+ if (arg0Node === eff._) return;
712
+ const arg0NodeScope = context.sourceCode.getScope(arg0Node);
713
+ const arg0NodeReferences = VAR5__namespace.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
714
+ const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
711
715
  if (!isReferencedToComponentScope) {
712
716
  context.report({
713
717
  messageId: "noUnnecessaryUseMemo",
@@ -746,7 +750,7 @@ var no_useless_custom_hooks_default = createRule({
746
750
  "Program:exit"(node) {
747
751
  const allHooks = ctx.getAllHooks(node);
748
752
  for (const { name: name2, node: node2, hookCalls } of allHooks.values()) {
749
- if (AST2__namespace.isEmptyFunction(node2)) {
753
+ if (AST__namespace.isEmptyFunction(node2)) {
750
754
  continue;
751
755
  }
752
756
  if (hookCalls.length > 0) {
@@ -759,7 +763,7 @@ var no_useless_custom_hooks_default = createRule({
759
763
  messageId: "noUselessCustomHooks",
760
764
  node: node2,
761
765
  data: {
762
- name: name2.value
766
+ name: name2
763
767
  }
764
768
  });
765
769
  }
@@ -803,11 +807,11 @@ var prefer_use_state_lazy_initialization_default = createRule({
803
807
  if (useStateInput == null) {
804
808
  return;
805
809
  }
806
- const nestedCallExpressions = AST2__namespace.getNestedCallExpressions(useStateInput);
810
+ const nestedCallExpressions = AST__namespace.getNestedCallExpressions(useStateInput);
807
811
  const hasFunctionCall = nestedCallExpressions.some((n) => {
808
812
  return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
809
813
  });
810
- const hasNewCall = AST2__namespace.getNestedNewExpressions(useStateInput).some((n) => {
814
+ const hasNewCall = AST__namespace.getNestedNewExpressions(useStateInput).some((n) => {
811
815
  return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
812
816
  });
813
817
  if (!hasFunctionCall && !hasNewCall) {
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import * as AST2 from '@eslint-react/ast';
1
+ import * as AST from '@eslint-react/ast';
2
2
  import { isReactHookCallWithNameAlias, isReactHookCall, isUseCallbackCall, isReactHookCallWithNameLoose, isUseMemoCall, useHookCollector, isUseStateCall, isReactHookName } from '@eslint-react/core';
3
- import { O, F } from '@eslint-react/eff';
3
+ import { _, identity, returnTrue } from '@eslint-react/eff';
4
4
  import { createRuleForPlugin, getSettingsFromContext } from '@eslint-react/shared';
5
5
  import * as VAR5 from '@eslint-react/var';
6
6
  import { AST_NODE_TYPES } from '@typescript-eslint/types';
@@ -8,17 +8,18 @@ import { match } from 'ts-pattern';
8
8
 
9
9
  // package.json
10
10
  var name = "eslint-plugin-react-hooks-extra";
11
- var version = "1.23.3-next.7";
11
+ var version = "1.24.0-beta.0";
12
12
  var createRule = createRuleForPlugin("hooks-extra");
13
- function isFromHookCall(name2, context, settings, predicate = F.constTrue) {
13
+ function isFromHookCall(name2, context, settings, predicate = returnTrue) {
14
14
  const hookAlias = settings.additionalHooks?.[name2] ?? [];
15
- return (topLevelId) => F.pipe(
16
- VAR5.findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
17
- O.flatMap(VAR5.getVariableNode(0)),
18
- O.filter(AST2.is(AST_NODE_TYPES.CallExpression)),
19
- O.filter(isReactHookCallWithNameAlias(name2, context, hookAlias)),
20
- O.exists((call) => predicate(topLevelId, call))
21
- );
15
+ return (topLevelId) => {
16
+ const variable = VAR5.findVariable(topLevelId, context.sourceCode.getScope(topLevelId));
17
+ const variableNode = VAR5.getVariableNode(variable, 0);
18
+ if (variableNode == null) return false;
19
+ if (variableNode.type !== AST_NODE_TYPES.CallExpression) return false;
20
+ if (!isReactHookCallWithNameAlias(name2, context, hookAlias)(variableNode)) return false;
21
+ return predicate(topLevelId, variableNode);
22
+ };
22
23
  }
23
24
  function isFromUseStateCall(context, settings) {
24
25
  const predicate = (topLevelId, call) => {
@@ -49,8 +50,13 @@ function isSetFunctionCall(context, settings) {
49
50
  if (!isAt || index == null) {
50
51
  return false;
51
52
  }
52
- const initialScope = context.sourceCode.getScope(node);
53
- return O.exists(VAR5.getStaticValue(index, initialScope), (v) => v === 1) && isIdFromUseStateCall(callee.object);
53
+ const indexScope = context.sourceCode.getScope(node);
54
+ const indexValue = VAR5.toResolved({
55
+ kind: "lazy",
56
+ node: index,
57
+ initialScope: indexScope
58
+ }).value;
59
+ return indexValue === 1 && isIdFromUseStateCall(callee.object);
54
60
  }
55
61
  // const [data, setData] = useState();
56
62
  // setData();
@@ -63,8 +69,14 @@ function isSetFunctionCall(context, settings) {
63
69
  if (!("name" in node.callee.object)) {
64
70
  return false;
65
71
  }
66
- const initialScope = context.sourceCode.getScope(node);
67
- return O.exists(VAR5.getStaticValue(node.callee.property, initialScope), (v) => v === 1) && isIdFromUseStateCall(node.callee.object);
72
+ const property = node.callee.property;
73
+ const propertyScope = context.sourceCode.getScope(node);
74
+ const propertyValue = VAR5.toResolved({
75
+ kind: "lazy",
76
+ node: property,
77
+ initialScope: propertyScope
78
+ }).value;
79
+ return propertyValue === 1 && isIdFromUseStateCall(node.callee.object);
68
80
  }
69
81
  default: {
70
82
  return false;
@@ -125,8 +137,8 @@ var no_direct_set_state_in_use_effect_default = createRule({
125
137
  const isUseCallbackCall2 = isReactHookCallWithNameAlias("useCallback", context, additionalHooks.useCallback ?? []);
126
138
  const isSetStateCall = isSetFunctionCall(context, settings);
127
139
  const isIdFromUseStateCall = isFromUseStateCall(context, settings);
128
- const functionStack = [];
129
- const setupFunctionRef = { current: O.none() };
140
+ const functionEntries = [];
141
+ const setupFunctionRef = { current: null };
130
142
  const setupFunctionIdentifiers = [];
131
143
  const indFunctionCalls = [];
132
144
  const indSetStateCalls = /* @__PURE__ */ new WeakMap();
@@ -134,10 +146,12 @@ var no_direct_set_state_in_use_effect_default = createRule({
134
146
  const indSetStateCallsInUseEffectSetup = /* @__PURE__ */ new Map();
135
147
  const indSetStateCallsInUseMemoOrCallback = /* @__PURE__ */ new WeakMap();
136
148
  const onSetupFunctionEnter = (node) => {
137
- setupFunctionRef.current = O.some(node);
149
+ setupFunctionRef.current = node;
138
150
  };
139
151
  const onSetupFunctionExit = (node) => {
140
- setupFunctionRef.current = O.filter(setupFunctionRef.current, (current) => current !== node);
152
+ if (setupFunctionRef.current === node) {
153
+ setupFunctionRef.current = null;
154
+ }
141
155
  };
142
156
  function isSetupFunction(node) {
143
157
  return node.parent?.type === AST_NODE_TYPES.CallExpression && node.parent.callee !== node && isUseEffectLikeCall(node.parent);
@@ -146,26 +160,26 @@ var no_direct_set_state_in_use_effect_default = createRule({
146
160
  return match(node).when(isUseStateCall2, () => "useState").when(isUseEffectLikeCall, () => "useEffect").when(isSetStateCall, () => "setState").when(isThenCall, () => "then").otherwise(() => "other");
147
161
  }
148
162
  function getFunctionKind(node) {
149
- return match(node).when(isSetupFunction, () => "setup").when(AST2.isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
163
+ return match(node).when(isSetupFunction, () => "setup").when(AST.isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
150
164
  }
151
165
  return {
152
166
  ":function"(node) {
153
167
  const kind = getFunctionKind(node);
154
- functionStack.push({ kind, node });
168
+ functionEntries.push({ kind, node });
155
169
  if (kind === "setup") {
156
170
  onSetupFunctionEnter(node);
157
171
  }
158
172
  },
159
173
  ":function:exit"(node) {
160
- const { kind } = functionStack.at(-1) ?? {};
174
+ const { kind } = functionEntries.at(-1) ?? {};
161
175
  if (kind === "setup") {
162
176
  onSetupFunctionExit(node);
163
177
  }
164
- functionStack.pop();
178
+ functionEntries.pop();
165
179
  },
166
180
  CallExpression(node) {
167
- const setupFunction = O.getOrNull(setupFunctionRef.current);
168
- const pEntry = functionStack.at(-1);
181
+ const setupFunction = setupFunctionRef.current;
182
+ const pEntry = functionEntries.at(-1);
169
183
  if (pEntry?.node.async) {
170
184
  return;
171
185
  }
@@ -185,28 +199,28 @@ var no_direct_set_state_in_use_effect_default = createRule({
185
199
  return;
186
200
  }
187
201
  default: {
188
- const mbVariableDeclarator = AST2.findParentNodeGuard(node, isVariableDeclaratorFromHookCall);
189
- if (O.isNone(mbVariableDeclarator)) {
202
+ const variableDeclarator = AST.findParentNodeGuard(node, isVariableDeclaratorFromHookCall);
203
+ if (variableDeclarator === _) {
190
204
  const calls = indSetStateCalls.get(pEntry.node) ?? [];
191
205
  indSetStateCalls.set(pEntry.node, [...calls, node]);
192
206
  return;
193
207
  }
194
- const vd = mbVariableDeclarator.value;
195
- const prevs = indSetStateCallsInUseMemoOrCallback.get(vd.init) ?? [];
196
- indSetStateCallsInUseMemoOrCallback.set(vd.init, [...prevs, node]);
208
+ const init = variableDeclarator.init;
209
+ const prevs = indSetStateCallsInUseMemoOrCallback.get(init) ?? [];
210
+ indSetStateCallsInUseMemoOrCallback.set(init, [...prevs, node]);
197
211
  }
198
212
  }
199
213
  }).with("useEffect", () => {
200
- if (AST2.isFunction(node.arguments.at(0))) {
214
+ if (AST.isFunction(node.arguments.at(0))) {
201
215
  return;
202
216
  }
203
- setupFunctionIdentifiers.push(...AST2.getNestedIdentifiers(node));
217
+ setupFunctionIdentifiers.push(...AST.getNestedIdentifiers(node));
204
218
  }).with("other", () => {
205
219
  if (pEntry?.node !== setupFunction) {
206
220
  return;
207
221
  }
208
222
  indFunctionCalls.push(node);
209
- }).otherwise(F.constVoid);
223
+ }).otherwise(() => _);
210
224
  },
211
225
  Identifier(node) {
212
226
  if (node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) {
@@ -224,11 +238,10 @@ var no_direct_set_state_in_use_effect_default = createRule({
224
238
  if (!isUseMemoCall2(parent)) {
225
239
  break;
226
240
  }
227
- const mbVariableDeclarator = AST2.findParentNodeGuard(parent, isVariableDeclaratorFromHookCall);
228
- if (O.isNone(mbVariableDeclarator)) {
241
+ const variableDeclarator = AST.findParentNodeGuard(parent, isVariableDeclaratorFromHookCall);
242
+ if (variableDeclarator == null) {
229
243
  break;
230
244
  }
231
- const variableDeclarator = mbVariableDeclarator.value;
232
245
  const calls = indSetStateCallsInUseEffectArg0.get(variableDeclarator.init) ?? [];
233
246
  indSetStateCallsInUseEffectArg0.set(variableDeclarator.init, [...calls, node]);
234
247
  break;
@@ -238,11 +251,10 @@ var no_direct_set_state_in_use_effect_default = createRule({
238
251
  break;
239
252
  }
240
253
  if (isUseCallbackCall2(node.parent)) {
241
- const mbVariableDeclarator = AST2.findParentNodeGuard(node.parent, isVariableDeclaratorFromHookCall);
242
- if (O.isNone(mbVariableDeclarator)) {
254
+ const variableDeclarator = AST.findParentNodeGuard(node.parent, isVariableDeclaratorFromHookCall);
255
+ if (variableDeclarator == null) {
243
256
  break;
244
257
  }
245
- const variableDeclarator = mbVariableDeclarator.value;
246
258
  const prevs = indSetStateCallsInUseEffectArg0.get(variableDeclarator.init) ?? [];
247
259
  indSetStateCallsInUseEffectArg0.set(variableDeclarator.init, [...prevs, node]);
248
260
  }
@@ -256,7 +268,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
256
268
  },
257
269
  "Program:exit"() {
258
270
  const getSetStateCalls = (id, initialScope) => {
259
- const node = O.flatMap(VAR5.findVariable(id, initialScope), VAR5.getVariableNode(0)).pipe(O.getOrNull);
271
+ const node = VAR5.getVariableNode(VAR5.findVariable(id, initialScope), 0);
260
272
  switch (node?.type) {
261
273
  case AST_NODE_TYPES.ArrowFunctionExpression:
262
274
  case AST_NODE_TYPES.FunctionDeclaration:
@@ -267,7 +279,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
267
279
  }
268
280
  return [];
269
281
  };
270
- for (const [_, calls] of indSetStateCallsInUseEffectSetup) {
282
+ for (const [, calls] of indSetStateCallsInUseEffectSetup) {
271
283
  for (const call of calls) {
272
284
  context.report({
273
285
  messageId: "noDirectSetStateInUseEffect",
@@ -287,7 +299,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
287
299
  messageId: "noDirectSetStateInUseEffect",
288
300
  node: setStateCall,
289
301
  data: {
290
- name: AST2.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
302
+ name: AST.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
291
303
  }
292
304
  });
293
305
  }
@@ -299,7 +311,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
299
311
  messageId: "noDirectSetStateInUseEffect",
300
312
  node: setStateCall,
301
313
  data: {
302
- name: AST2.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
314
+ name: AST.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
303
315
  }
304
316
  });
305
317
  }
@@ -342,8 +354,8 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
342
354
  const isUseCallbackCall2 = isReactHookCallWithNameAlias("useCallback", context, additionalHooks.useCallback ?? []);
343
355
  const isSetStateCall = isSetFunctionCall(context, settings);
344
356
  const isIdFromUseStateCall = isFromUseStateCall(context, settings);
345
- const functionStack = [];
346
- const setupFunctionRef = { current: O.none() };
357
+ const functionEntries = [];
358
+ const setupFunctionRef = { current: null };
347
359
  const setupFunctionIdentifiers = [];
348
360
  const indFunctionCalls = [];
349
361
  const indSetStateCalls = /* @__PURE__ */ new WeakMap();
@@ -351,10 +363,12 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
351
363
  const indSetStateCallsInUseLayoutEffectSetup = /* @__PURE__ */ new Map();
352
364
  const indSetStateCallsInUseMemoOrCallback = /* @__PURE__ */ new WeakMap();
353
365
  const onSetupFunctionEnter = (node) => {
354
- setupFunctionRef.current = O.some(node);
366
+ setupFunctionRef.current = node;
355
367
  };
356
368
  const onSetupFunctionExit = (node) => {
357
- setupFunctionRef.current = O.filter(setupFunctionRef.current, (current) => current !== node);
369
+ if (setupFunctionRef.current === node) {
370
+ setupFunctionRef.current = null;
371
+ }
358
372
  };
359
373
  function isSetupFunction(node) {
360
374
  return node.parent?.type === AST_NODE_TYPES.CallExpression && node.parent.callee !== node && isUseLayoutEffectLikeCall(node.parent);
@@ -363,26 +377,26 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
363
377
  return match(node).when(isUseStateCall2, () => "useState").when(isUseLayoutEffectLikeCall, () => "useLayoutEffect").when(isSetStateCall, () => "setState").when(isThenCall, () => "then").otherwise(() => "other");
364
378
  }
365
379
  function getFunctionKind(node) {
366
- return match(node).when(isSetupFunction, () => "setup").when(AST2.isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
380
+ return match(node).when(isSetupFunction, () => "setup").when(AST.isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
367
381
  }
368
382
  return {
369
383
  ":function"(node) {
370
384
  const kind = getFunctionKind(node);
371
- functionStack.push({ kind, node });
385
+ functionEntries.push({ kind, node });
372
386
  if (kind === "setup") {
373
387
  onSetupFunctionEnter(node);
374
388
  }
375
389
  },
376
390
  ":function:exit"(node) {
377
- const { kind } = functionStack.at(-1) ?? {};
391
+ const { kind } = functionEntries.at(-1) ?? {};
378
392
  if (kind === "setup") {
379
393
  onSetupFunctionExit(node);
380
394
  }
381
- functionStack.pop();
395
+ functionEntries.pop();
382
396
  },
383
397
  CallExpression(node) {
384
- const setupFunction = O.getOrNull(setupFunctionRef.current);
385
- const pEntry = functionStack.at(-1);
398
+ const setupFunction = setupFunctionRef.current;
399
+ const pEntry = functionEntries.at(-1);
386
400
  if (pEntry?.node.async) {
387
401
  return;
388
402
  }
@@ -402,28 +416,28 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
402
416
  return;
403
417
  }
404
418
  default: {
405
- const mbVariableDeclarator = AST2.findParentNodeGuard(node, isVariableDeclaratorFromHookCall);
406
- if (O.isNone(mbVariableDeclarator)) {
419
+ const variableDeclarator = AST.findParentNodeGuard(node, isVariableDeclaratorFromHookCall);
420
+ if (variableDeclarator === _) {
407
421
  const calls = indSetStateCalls.get(pEntry.node) ?? [];
408
422
  indSetStateCalls.set(pEntry.node, [...calls, node]);
409
423
  return;
410
424
  }
411
- const vd = mbVariableDeclarator.value;
412
- const prevs = indSetStateCallsInUseMemoOrCallback.get(vd.init) ?? [];
413
- indSetStateCallsInUseMemoOrCallback.set(vd.init, [...prevs, node]);
425
+ const init = variableDeclarator.init;
426
+ const prevs = indSetStateCallsInUseMemoOrCallback.get(init) ?? [];
427
+ indSetStateCallsInUseMemoOrCallback.set(init, [...prevs, node]);
414
428
  }
415
429
  }
416
430
  }).with("useLayoutEffect", () => {
417
- if (AST2.isFunction(node.arguments.at(0))) {
431
+ if (AST.isFunction(node.arguments.at(0))) {
418
432
  return;
419
433
  }
420
- setupFunctionIdentifiers.push(...AST2.getNestedIdentifiers(node));
434
+ setupFunctionIdentifiers.push(...AST.getNestedIdentifiers(node));
421
435
  }).with("other", () => {
422
436
  if (pEntry?.node !== setupFunction) {
423
437
  return;
424
438
  }
425
439
  indFunctionCalls.push(node);
426
- }).otherwise(F.constVoid);
440
+ }).otherwise(() => _);
427
441
  },
428
442
  Identifier(node) {
429
443
  if (node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) {
@@ -441,11 +455,10 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
441
455
  if (!isUseMemoCall2(parent)) {
442
456
  break;
443
457
  }
444
- const mbVariableDeclarator = AST2.findParentNodeGuard(parent, isVariableDeclaratorFromHookCall);
445
- if (O.isNone(mbVariableDeclarator)) {
458
+ const variableDeclarator = AST.findParentNodeGuard(parent, isVariableDeclaratorFromHookCall);
459
+ if (variableDeclarator == null) {
446
460
  break;
447
461
  }
448
- const variableDeclarator = mbVariableDeclarator.value;
449
462
  const calls = indSetStateCallsInUseLayoutEffectArg0.get(variableDeclarator.init) ?? [];
450
463
  indSetStateCallsInUseLayoutEffectArg0.set(variableDeclarator.init, [...calls, node]);
451
464
  break;
@@ -455,11 +468,10 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
455
468
  break;
456
469
  }
457
470
  if (isUseCallbackCall2(node.parent)) {
458
- const mbVariableDeclarator = AST2.findParentNodeGuard(node.parent, isVariableDeclaratorFromHookCall);
459
- if (O.isNone(mbVariableDeclarator)) {
471
+ const variableDeclarator = AST.findParentNodeGuard(node.parent, isVariableDeclaratorFromHookCall);
472
+ if (variableDeclarator == null) {
460
473
  break;
461
474
  }
462
- const variableDeclarator = mbVariableDeclarator.value;
463
475
  const prevs = indSetStateCallsInUseLayoutEffectArg0.get(variableDeclarator.init) ?? [];
464
476
  indSetStateCallsInUseLayoutEffectArg0.set(variableDeclarator.init, [...prevs, node]);
465
477
  }
@@ -473,7 +485,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
473
485
  },
474
486
  "Program:exit"() {
475
487
  const getSetStateCalls = (id, initialScope) => {
476
- const node = O.flatMap(VAR5.findVariable(id, initialScope), VAR5.getVariableNode(0)).pipe(O.getOrNull);
488
+ const node = VAR5.getVariableNode(VAR5.findVariable(id, initialScope), 0);
477
489
  switch (node?.type) {
478
490
  case AST_NODE_TYPES.ArrowFunctionExpression:
479
491
  case AST_NODE_TYPES.FunctionDeclaration:
@@ -484,7 +496,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
484
496
  }
485
497
  return [];
486
498
  };
487
- for (const [_, calls] of indSetStateCallsInUseLayoutEffectSetup) {
499
+ for (const [, calls] of indSetStateCallsInUseLayoutEffectSetup) {
488
500
  for (const call of calls) {
489
501
  context.report({
490
502
  messageId: "noDirectSetStateInUseLayoutEffect",
@@ -504,7 +516,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
504
516
  messageId: "noDirectSetStateInUseLayoutEffect",
505
517
  node: setStateCall,
506
518
  data: {
507
- name: AST2.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
519
+ name: AST.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
508
520
  }
509
521
  });
510
522
  }
@@ -516,7 +528,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
516
528
  messageId: "noDirectSetStateInUseLayoutEffect",
517
529
  node: setStateCall,
518
530
  data: {
519
- name: AST2.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
531
+ name: AST.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
520
532
  }
521
533
  });
522
534
  }
@@ -559,43 +571,41 @@ var no_unnecessary_use_callback_default = createRule({
559
571
  }
560
572
  const scope = context.sourceCode.getScope(node);
561
573
  const component = scope.block;
562
- if (!AST2.isFunction(component)) {
574
+ if (!AST.isFunction(component)) {
563
575
  return;
564
576
  }
565
577
  const [arg0, arg1] = node.arguments;
566
578
  if (arg0 == null || arg1 == null) {
567
579
  return;
568
580
  }
569
- const hasEmptyDeps = F.pipe(
570
- match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
571
- return F.pipe(
572
- VAR5.findVariable(n.name, initialScope),
573
- O.flatMap(VAR5.getVariableNode(0)),
574
- O.filter(AST2.is(AST_NODE_TYPES.ArrayExpression))
575
- );
576
- }).otherwise(O.none),
577
- O.exists((x) => x.elements.length === 0)
578
- );
581
+ const hasEmptyDeps = match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
582
+ const variable = VAR5.findVariable(n.name, initialScope);
583
+ const variableNode = VAR5.getVariableNode(variable, 0);
584
+ if (variableNode?.type !== AST_NODE_TYPES.ArrayExpression) {
585
+ return false;
586
+ }
587
+ return variableNode.elements.length === 0;
588
+ }).otherwise(() => false);
579
589
  if (!hasEmptyDeps) {
580
590
  return;
581
591
  }
582
- const isReferencedToComponentScope = F.pipe(
583
- match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
584
- if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) {
585
- return O.some(n.body);
586
- }
587
- return O.some(n);
588
- }).with({ type: AST_NODE_TYPES.FunctionExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
589
- return F.pipe(
590
- VAR5.findVariable(n.name, initialScope),
591
- O.flatMap(VAR5.getVariableNode(0)),
592
- O.filter(AST2.isFunction)
593
- );
594
- }).otherwise(O.none),
595
- O.map((n) => context.sourceCode.getScope(n)),
596
- O.map((s) => VAR5.getChidScopes(s).flatMap((x) => x.references)),
597
- O.exists((refs) => refs.some((x) => x.resolved?.scope.block === component))
598
- );
592
+ const arg0Node = match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
593
+ if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) {
594
+ return n.body;
595
+ }
596
+ return n;
597
+ }).with({ type: AST_NODE_TYPES.FunctionExpression }, identity).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
598
+ const variable = VAR5.findVariable(n.name, initialScope);
599
+ const variableNode = VAR5.getVariableNode(variable, 0);
600
+ if (variableNode?.type !== AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== AST_NODE_TYPES.FunctionExpression) {
601
+ return _;
602
+ }
603
+ return variableNode;
604
+ }).otherwise(() => _);
605
+ if (arg0Node === _) return;
606
+ const arg0NodeScope = context.sourceCode.getScope(arg0Node);
607
+ const arg0NodeReferences = VAR5.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
608
+ const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
599
609
  if (!isReferencedToComponentScope) {
600
610
  context.report({
601
611
  messageId: "noUnnecessaryUseCallback",
@@ -640,51 +650,45 @@ var no_unnecessary_use_memo_default = createRule({
640
650
  }
641
651
  const scope = context.sourceCode.getScope(node);
642
652
  const component = scope.block;
643
- if (!AST2.isFunction(component)) {
653
+ if (!AST.isFunction(component)) {
644
654
  return;
645
655
  }
646
656
  const [arg0, arg1] = node.arguments;
647
657
  if (arg0 == null || arg1 == null) {
648
658
  return;
649
659
  }
650
- const hasCallInArg0 = F.pipe(
651
- O.some(arg0),
652
- O.filter((n) => AST2.isFunction(n)),
653
- O.exists((n) => [...AST2.getNestedCallExpressions(n.body), ...AST2.getNestedNewExpressions(n.body)].length > 0)
654
- );
660
+ const hasCallInArg0 = AST.isFunction(arg0) && [...AST.getNestedCallExpressions(arg0.body), ...AST.getNestedNewExpressions(arg0.body)].length > 0;
655
661
  if (hasCallInArg0) {
656
662
  return;
657
663
  }
658
- const hasEmptyDeps = F.pipe(
659
- match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
660
- return F.pipe(
661
- VAR5.findVariable(n.name, initialScope),
662
- O.flatMap(VAR5.getVariableNode(0)),
663
- O.filter(AST2.is(AST_NODE_TYPES.ArrayExpression))
664
- );
665
- }).otherwise(O.none),
666
- O.exists((x) => x.elements.length === 0)
667
- );
664
+ const hasEmptyDeps = match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
665
+ const variable = VAR5.findVariable(n.name, initialScope);
666
+ const variableNode = VAR5.getVariableNode(variable, 0);
667
+ if (variableNode?.type !== AST_NODE_TYPES.ArrayExpression) {
668
+ return false;
669
+ }
670
+ return variableNode.elements.length === 0;
671
+ }).otherwise(() => false);
668
672
  if (!hasEmptyDeps) {
669
673
  return;
670
674
  }
671
- const isReferencedToComponentScope = F.pipe(
672
- match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
673
- if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) {
674
- return O.some(n.body);
675
- }
676
- return O.some(n);
677
- }).with({ type: AST_NODE_TYPES.FunctionExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
678
- return F.pipe(
679
- VAR5.findVariable(n.name, initialScope),
680
- O.flatMap(VAR5.getVariableNode(0)),
681
- O.filter(AST2.isFunction)
682
- );
683
- }).otherwise(O.none),
684
- O.map((n) => context.sourceCode.getScope(n)),
685
- O.map((s) => VAR5.getChidScopes(s).flatMap((x) => x.references)),
686
- O.exists((refs) => refs.some((x) => x.resolved?.scope.block === component))
687
- );
675
+ const arg0Node = match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
676
+ if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) {
677
+ return n.body;
678
+ }
679
+ return n;
680
+ }).with({ type: AST_NODE_TYPES.FunctionExpression }, identity).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
681
+ const variable = VAR5.findVariable(n.name, initialScope);
682
+ const variableNode = VAR5.getVariableNode(variable, 0);
683
+ if (variableNode?.type !== AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== AST_NODE_TYPES.FunctionExpression) {
684
+ return _;
685
+ }
686
+ return variableNode;
687
+ }).otherwise(() => _);
688
+ if (arg0Node === _) return;
689
+ const arg0NodeScope = context.sourceCode.getScope(arg0Node);
690
+ const arg0NodeReferences = VAR5.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
691
+ const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
688
692
  if (!isReferencedToComponentScope) {
689
693
  context.report({
690
694
  messageId: "noUnnecessaryUseMemo",
@@ -723,7 +727,7 @@ var no_useless_custom_hooks_default = createRule({
723
727
  "Program:exit"(node) {
724
728
  const allHooks = ctx.getAllHooks(node);
725
729
  for (const { name: name2, node: node2, hookCalls } of allHooks.values()) {
726
- if (AST2.isEmptyFunction(node2)) {
730
+ if (AST.isEmptyFunction(node2)) {
727
731
  continue;
728
732
  }
729
733
  if (hookCalls.length > 0) {
@@ -736,7 +740,7 @@ var no_useless_custom_hooks_default = createRule({
736
740
  messageId: "noUselessCustomHooks",
737
741
  node: node2,
738
742
  data: {
739
- name: name2.value
743
+ name: name2
740
744
  }
741
745
  });
742
746
  }
@@ -780,11 +784,11 @@ var prefer_use_state_lazy_initialization_default = createRule({
780
784
  if (useStateInput == null) {
781
785
  return;
782
786
  }
783
- const nestedCallExpressions = AST2.getNestedCallExpressions(useStateInput);
787
+ const nestedCallExpressions = AST.getNestedCallExpressions(useStateInput);
784
788
  const hasFunctionCall = nestedCallExpressions.some((n) => {
785
789
  return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
786
790
  });
787
- const hasNewCall = AST2.getNestedNewExpressions(useStateInput).some((n) => {
791
+ const hasNewCall = AST.getNestedNewExpressions(useStateInput).some((n) => {
788
792
  return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
789
793
  });
790
794
  if (!hasFunctionCall && !hasNewCall) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-hooks-extra",
3
- "version": "1.23.3-next.7",
3
+ "version": "1.24.0-beta.0",
4
4
  "description": "ESLint React's ESLint plugin for React Hooks related rules.",
5
5
  "keywords": [
6
6
  "react",
@@ -11,13 +11,13 @@
11
11
  "eslint-plugin",
12
12
  "eslint-plugin-react-hooks-extra"
13
13
  ],
14
- "homepage": "https://github.com/rEl1cx/eslint-react",
14
+ "homepage": "https://github.com/Rel1cx/eslint-react",
15
15
  "bugs": {
16
- "url": "https://github.com/rEl1cx/eslint-react/issues"
16
+ "url": "https://github.com/Rel1cx/eslint-react/issues"
17
17
  },
18
18
  "repository": {
19
19
  "type": "git",
20
- "url": "git+https://github.com/rEl1cx/eslint-react.git",
20
+ "url": "git+https://github.com/Rel1cx/eslint-react.git",
21
21
  "directory": "packages/plugins/eslint-plugin-react-hooks-extra"
22
22
  },
23
23
  "license": "MIT",
@@ -48,13 +48,13 @@
48
48
  "@typescript-eslint/utils": "^8.19.1",
49
49
  "string-ts": "^2.2.0",
50
50
  "ts-pattern": "^5.6.0",
51
- "@eslint-react/core": "1.23.3-next.7",
52
- "@eslint-react/ast": "1.23.3-next.7",
53
- "@eslint-react/eff": "1.23.3-next.7",
54
- "@eslint-react/jsx": "1.23.3-next.7",
55
- "@eslint-react/shared": "1.23.3-next.7",
56
- "@eslint-react/types": "1.23.3-next.7",
57
- "@eslint-react/var": "1.23.3-next.7"
51
+ "@eslint-react/ast": "1.24.0-beta.0",
52
+ "@eslint-react/core": "1.24.0-beta.0",
53
+ "@eslint-react/jsx": "1.24.0-beta.0",
54
+ "@eslint-react/shared": "1.24.0-beta.0",
55
+ "@eslint-react/var": "1.24.0-beta.0",
56
+ "@eslint-react/eff": "1.24.0-beta.0",
57
+ "@eslint-react/types": "1.24.0-beta.0"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@types/react": "^19.0.4",