eslint-plugin-react-hooks-extra 1.33.0 → 1.34.0-beta.1

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 +200 -200
  2. package/dist/index.mjs +200 -200
  3. package/package.json +7 -7
package/dist/index.js CHANGED
@@ -50,7 +50,7 @@ var rules = {
50
50
 
51
51
  // package.json
52
52
  var name2 = "eslint-plugin-react-hooks-extra";
53
- var version = "1.33.0";
53
+ var version = "1.34.0-beta.1";
54
54
  var createRule = shared.createRuleForPlugin("hooks-extra");
55
55
  function isFromHookCall(context, name3, settings, predicate = eff.constTrue) {
56
56
  const hookAlias = settings.additionalHooks[name3] ?? [];
@@ -331,17 +331,18 @@ var no_direct_set_state_in_use_effect_default = createRule({
331
331
  schema: []
332
332
  },
333
333
  name: RULE_NAME,
334
- create(context) {
335
- if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
336
- return useNoDirectSetStateInUseEffect(context, {
337
- onViolation(ctx, node, data) {
338
- ctx.report({ messageId: "noDirectSetStateInUseEffect", node, data });
339
- },
340
- useEffectKind: "useEffect"
341
- });
342
- },
334
+ create,
343
335
  defaultOptions: []
344
336
  });
337
+ function create(context) {
338
+ if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
339
+ return useNoDirectSetStateInUseEffect(context, {
340
+ onViolation(ctx, node, data) {
341
+ ctx.report({ messageId: "noDirectSetStateInUseEffect", node, data });
342
+ },
343
+ useEffectKind: "useEffect"
344
+ });
345
+ }
345
346
 
346
347
  // src/rules/no-direct-set-state-in-use-layout-effect.ts
347
348
  var RULE_NAME2 = "no-direct-set-state-in-use-layout-effect";
@@ -361,17 +362,18 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
361
362
  schema: []
362
363
  },
363
364
  name: RULE_NAME2,
364
- create(context) {
365
- if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
366
- return useNoDirectSetStateInUseEffect(context, {
367
- onViolation(ctx, node, data) {
368
- ctx.report({ messageId: "noDirectSetStateInUseLayoutEffect", node, data });
369
- },
370
- useEffectKind: "useLayoutEffect"
371
- });
372
- },
365
+ create: create2,
373
366
  defaultOptions: []
374
367
  });
368
+ function create2(context) {
369
+ if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
370
+ return useNoDirectSetStateInUseEffect(context, {
371
+ onViolation(ctx, node, data) {
372
+ ctx.report({ messageId: "noDirectSetStateInUseLayoutEffect", node, data });
373
+ },
374
+ useEffectKind: "useLayoutEffect"
375
+ });
376
+ }
375
377
  var RULE_NAME3 = "no-unnecessary-use-callback";
376
378
  var RULE_FEATURES3 = [
377
379
  "CHK"
@@ -389,68 +391,67 @@ var no_unnecessary_use_callback_default = createRule({
389
391
  schema: []
390
392
  },
391
393
  name: RULE_NAME3,
392
- create(context) {
393
- if (!context.sourceCode.text.includes("use")) {
394
- return {};
395
- }
396
- const alias = shared.getSettingsFromContext(context).additionalHooks.useCallback ?? [];
397
- return {
398
- CallExpression(node) {
399
- if (!core.isReactHookCall(node)) {
400
- return;
401
- }
402
- const initialScope = context.sourceCode.getScope(node);
403
- if (!core.isUseCallbackCall(context, node) && !alias.some(core.isReactHookCallWithNameLoose(node))) {
404
- return;
405
- }
406
- const scope = context.sourceCode.getScope(node);
407
- const component = scope.block;
408
- if (!AST__namespace.isFunction(component)) {
409
- return;
410
- }
411
- const [arg0, arg1] = node.arguments;
412
- if (arg0 == null || arg1 == null) {
413
- return;
394
+ create: create3,
395
+ defaultOptions: []
396
+ });
397
+ function create3(context) {
398
+ if (!context.sourceCode.text.includes("use")) return {};
399
+ const alias = shared.getSettingsFromContext(context).additionalHooks.useCallback ?? [];
400
+ return {
401
+ CallExpression(node) {
402
+ if (!core.isReactHookCall(node)) {
403
+ return;
404
+ }
405
+ const initialScope = context.sourceCode.getScope(node);
406
+ if (!core.isUseCallbackCall(context, node) && !alias.some(core.isReactHookCallWithNameLoose(node))) {
407
+ return;
408
+ }
409
+ const scope = context.sourceCode.getScope(node);
410
+ const component = scope.block;
411
+ if (!AST__namespace.isFunction(component)) {
412
+ return;
413
+ }
414
+ const [arg0, arg1] = node.arguments;
415
+ if (arg0 == null || arg1 == null) {
416
+ return;
417
+ }
418
+ 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) => {
419
+ const variable = VAR4__namespace.findVariable(n.name, initialScope);
420
+ const variableNode = VAR4__namespace.getVariableInitNode(variable, 0);
421
+ if (variableNode?.type !== types.AST_NODE_TYPES.ArrayExpression) {
422
+ return false;
414
423
  }
415
- 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) => {
416
- const variable = VAR4__namespace.findVariable(n.name, initialScope);
417
- const variableNode = VAR4__namespace.getVariableInitNode(variable, 0);
418
- if (variableNode?.type !== types.AST_NODE_TYPES.ArrayExpression) {
419
- return false;
420
- }
421
- return variableNode.elements.length === 0;
422
- }).otherwise(() => false);
423
- if (!hasEmptyDeps) {
424
- return;
424
+ return variableNode.elements.length === 0;
425
+ }).otherwise(() => false);
426
+ if (!hasEmptyDeps) {
427
+ return;
428
+ }
429
+ const arg0Node = tsPattern.match(arg0).with({ type: types.AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
430
+ if (n.body.type === types.AST_NODE_TYPES.ArrowFunctionExpression) {
431
+ return n.body;
425
432
  }
426
- const arg0Node = tsPattern.match(arg0).with({ type: types.AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
427
- if (n.body.type === types.AST_NODE_TYPES.ArrowFunctionExpression) {
428
- return n.body;
429
- }
430
- return n;
431
- }).with({ type: types.AST_NODE_TYPES.FunctionExpression }, eff.identity).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
432
- const variable = VAR4__namespace.findVariable(n.name, initialScope);
433
- const variableNode = VAR4__namespace.getVariableInitNode(variable, 0);
434
- if (variableNode?.type !== types.AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== types.AST_NODE_TYPES.FunctionExpression) {
435
- return eff._;
436
- }
437
- return variableNode;
438
- }).otherwise(() => eff._);
439
- if (arg0Node == null) return;
440
- const arg0NodeScope = context.sourceCode.getScope(arg0Node);
441
- const arg0NodeReferences = VAR4__namespace.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
442
- const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
443
- if (!isReferencedToComponentScope) {
444
- context.report({
445
- messageId: "noUnnecessaryUseCallback",
446
- node
447
- });
433
+ return n;
434
+ }).with({ type: types.AST_NODE_TYPES.FunctionExpression }, eff.identity).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
435
+ const variable = VAR4__namespace.findVariable(n.name, initialScope);
436
+ const variableNode = VAR4__namespace.getVariableInitNode(variable, 0);
437
+ if (variableNode?.type !== types.AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== types.AST_NODE_TYPES.FunctionExpression) {
438
+ return eff._;
448
439
  }
440
+ return variableNode;
441
+ }).otherwise(() => eff._);
442
+ if (arg0Node == null) return;
443
+ const arg0NodeScope = context.sourceCode.getScope(arg0Node);
444
+ const arg0NodeReferences = VAR4__namespace.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
445
+ const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
446
+ if (!isReferencedToComponentScope) {
447
+ context.report({
448
+ messageId: "noUnnecessaryUseCallback",
449
+ node
450
+ });
449
451
  }
450
- };
451
- },
452
- defaultOptions: []
453
- });
452
+ }
453
+ };
454
+ }
454
455
  var RULE_NAME4 = "no-unnecessary-use-memo";
455
456
  var RULE_FEATURES4 = [
456
457
  "CHK"
@@ -468,72 +469,71 @@ var no_unnecessary_use_memo_default = createRule({
468
469
  schema: []
469
470
  },
470
471
  name: RULE_NAME4,
471
- create(context) {
472
- if (!context.sourceCode.text.includes("use")) {
473
- return {};
474
- }
475
- const alias = shared.getSettingsFromContext(context).additionalHooks.useMemo ?? [];
476
- return {
477
- CallExpression(node) {
478
- if (!core.isReactHookCall(node)) {
479
- return;
480
- }
481
- const initialScope = context.sourceCode.getScope(node);
482
- if (!core.isUseMemoCall(context, node) && !alias.some(core.isReactHookCallWithNameLoose(node))) {
483
- return;
484
- }
485
- const scope = context.sourceCode.getScope(node);
486
- const component = scope.block;
487
- if (!AST__namespace.isFunction(component)) {
488
- return;
489
- }
490
- const [arg0, arg1] = node.arguments;
491
- if (arg0 == null || arg1 == null) {
492
- return;
493
- }
494
- const hasCallInArg0 = AST__namespace.isFunction(arg0) && [...AST__namespace.getNestedCallExpressions(arg0.body), ...AST__namespace.getNestedNewExpressions(arg0.body)].length > 0;
495
- if (hasCallInArg0) {
496
- return;
472
+ create: create4,
473
+ defaultOptions: []
474
+ });
475
+ function create4(context) {
476
+ if (!context.sourceCode.text.includes("use")) return {};
477
+ const alias = shared.getSettingsFromContext(context).additionalHooks.useMemo ?? [];
478
+ return {
479
+ CallExpression(node) {
480
+ if (!core.isReactHookCall(node)) {
481
+ return;
482
+ }
483
+ const initialScope = context.sourceCode.getScope(node);
484
+ if (!core.isUseMemoCall(context, node) && !alias.some(core.isReactHookCallWithNameLoose(node))) {
485
+ return;
486
+ }
487
+ const scope = context.sourceCode.getScope(node);
488
+ const component = scope.block;
489
+ if (!AST__namespace.isFunction(component)) {
490
+ return;
491
+ }
492
+ const [arg0, arg1] = node.arguments;
493
+ if (arg0 == null || arg1 == null) {
494
+ return;
495
+ }
496
+ const hasCallInArg0 = AST__namespace.isFunction(arg0) && [...AST__namespace.getNestedCallExpressions(arg0.body), ...AST__namespace.getNestedNewExpressions(arg0.body)].length > 0;
497
+ if (hasCallInArg0) {
498
+ return;
499
+ }
500
+ 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) => {
501
+ const variable = VAR4__namespace.findVariable(n.name, initialScope);
502
+ const variableNode = VAR4__namespace.getVariableInitNode(variable, 0);
503
+ if (variableNode?.type !== types.AST_NODE_TYPES.ArrayExpression) {
504
+ return false;
497
505
  }
498
- 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) => {
499
- const variable = VAR4__namespace.findVariable(n.name, initialScope);
500
- const variableNode = VAR4__namespace.getVariableInitNode(variable, 0);
501
- if (variableNode?.type !== types.AST_NODE_TYPES.ArrayExpression) {
502
- return false;
503
- }
504
- return variableNode.elements.length === 0;
505
- }).otherwise(() => false);
506
- if (!hasEmptyDeps) {
507
- return;
506
+ return variableNode.elements.length === 0;
507
+ }).otherwise(() => false);
508
+ if (!hasEmptyDeps) {
509
+ return;
510
+ }
511
+ const arg0Node = tsPattern.match(arg0).with({ type: types.AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
512
+ if (n.body.type === types.AST_NODE_TYPES.ArrowFunctionExpression) {
513
+ return n.body;
508
514
  }
509
- const arg0Node = tsPattern.match(arg0).with({ type: types.AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
510
- if (n.body.type === types.AST_NODE_TYPES.ArrowFunctionExpression) {
511
- return n.body;
512
- }
513
- return n;
514
- }).with({ type: types.AST_NODE_TYPES.FunctionExpression }, eff.identity).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
515
- const variable = VAR4__namespace.findVariable(n.name, initialScope);
516
- const variableNode = VAR4__namespace.getVariableInitNode(variable, 0);
517
- if (variableNode?.type !== types.AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== types.AST_NODE_TYPES.FunctionExpression) {
518
- return eff._;
519
- }
520
- return variableNode;
521
- }).otherwise(() => eff._);
522
- if (arg0Node == null) return;
523
- const arg0NodeScope = context.sourceCode.getScope(arg0Node);
524
- const arg0NodeReferences = VAR4__namespace.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
525
- const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
526
- if (!isReferencedToComponentScope) {
527
- context.report({
528
- messageId: "noUnnecessaryUseMemo",
529
- node
530
- });
515
+ return n;
516
+ }).with({ type: types.AST_NODE_TYPES.FunctionExpression }, eff.identity).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
517
+ const variable = VAR4__namespace.findVariable(n.name, initialScope);
518
+ const variableNode = VAR4__namespace.getVariableInitNode(variable, 0);
519
+ if (variableNode?.type !== types.AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== types.AST_NODE_TYPES.FunctionExpression) {
520
+ return eff._;
531
521
  }
522
+ return variableNode;
523
+ }).otherwise(() => eff._);
524
+ if (arg0Node == null) return;
525
+ const arg0NodeScope = context.sourceCode.getScope(arg0Node);
526
+ const arg0NodeReferences = VAR4__namespace.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
527
+ const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
528
+ if (!isReferencedToComponentScope) {
529
+ context.report({
530
+ messageId: "noUnnecessaryUseMemo",
531
+ node
532
+ });
532
533
  }
533
- };
534
- },
535
- defaultOptions: []
536
- });
534
+ }
535
+ };
536
+ }
537
537
  var RULE_NAME5 = "no-useless-custom-hooks";
538
538
  var RULE_FEATURES5 = [
539
539
  "CHK"
@@ -554,35 +554,36 @@ var no_useless_custom_hooks_default = createRule({
554
554
  schema: []
555
555
  },
556
556
  name: RULE_NAME5,
557
- create(context) {
558
- const { ctx, listeners } = core.useHookCollector();
559
- return {
560
- ...listeners,
561
- "Program:exit"(node) {
562
- const allHooks = ctx.getAllHooks(node);
563
- for (const { name: name3, node: node2, hookCalls } of allHooks.values()) {
564
- if (AST__namespace.isEmptyFunction(node2)) {
565
- continue;
566
- }
567
- if (hookCalls.length > 0) {
568
- continue;
569
- }
570
- if (isNodeContainsUseCallComments(context, node2)) {
571
- continue;
572
- }
573
- context.report({
574
- messageId: "noUselessCustomHooks",
575
- node: node2,
576
- data: {
577
- name: name3
578
- }
579
- });
580
- }
581
- }
582
- };
583
- },
557
+ create: create5,
584
558
  defaultOptions: []
585
559
  });
560
+ function create5(context) {
561
+ const { ctx, listeners } = core.useHookCollector();
562
+ return {
563
+ ...listeners,
564
+ "Program:exit"(node) {
565
+ const allHooks = ctx.getAllHooks(node);
566
+ for (const { name: name3, node: node2, hookCalls } of allHooks.values()) {
567
+ if (AST__namespace.isEmptyFunction(node2)) {
568
+ continue;
569
+ }
570
+ if (hookCalls.length > 0) {
571
+ continue;
572
+ }
573
+ if (isNodeContainsUseCallComments(context, node2)) {
574
+ continue;
575
+ }
576
+ context.report({
577
+ messageId: "noUselessCustomHooks",
578
+ node: node2,
579
+ data: {
580
+ name: name3
581
+ }
582
+ });
583
+ }
584
+ }
585
+ };
586
+ }
586
587
  var RULE_NAME6 = "prefer-use-state-lazy-initialization";
587
588
  var RULE_FEATURES6 = [
588
589
  "CHK"
@@ -601,42 +602,41 @@ var prefer_use_state_lazy_initialization_default = createRule({
601
602
  schema: []
602
603
  },
603
604
  name: RULE_NAME6,
604
- create(context) {
605
- if (!context.sourceCode.text.includes("use")) {
606
- return {};
607
- }
608
- const alias = shared.getSettingsFromContext(context).additionalHooks.useState ?? [];
609
- return {
610
- CallExpression(node) {
611
- if (!core.isReactHookCall(node)) {
612
- return;
613
- }
614
- if (!core.isUseStateCall(context, node) && !alias.some(core.isReactHookCallWithNameLoose(node))) {
615
- return;
616
- }
617
- const [useStateInput] = node.arguments;
618
- if (useStateInput == null) {
619
- return;
620
- }
621
- const nestedCallExpressions = AST__namespace.getNestedCallExpressions(useStateInput);
622
- const hasFunctionCall = nestedCallExpressions.some((n) => {
623
- return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
624
- });
625
- const hasNewCall = AST__namespace.getNestedNewExpressions(useStateInput).some((n) => {
626
- return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
627
- });
628
- if (!hasFunctionCall && !hasNewCall) {
629
- return;
630
- }
631
- context.report({
632
- messageId: "preferUseStateLazyInitialization",
633
- node: useStateInput
634
- });
635
- }
636
- };
637
- },
605
+ create: create6,
638
606
  defaultOptions: []
639
607
  });
608
+ function create6(context) {
609
+ if (!context.sourceCode.text.includes("use")) return {};
610
+ const alias = shared.getSettingsFromContext(context).additionalHooks.useState ?? [];
611
+ return {
612
+ CallExpression(node) {
613
+ if (!core.isReactHookCall(node)) {
614
+ return;
615
+ }
616
+ if (!core.isUseStateCall(context, node) && !alias.some(core.isReactHookCallWithNameLoose(node))) {
617
+ return;
618
+ }
619
+ const [useStateInput] = node.arguments;
620
+ if (useStateInput == null) {
621
+ return;
622
+ }
623
+ const nestedCallExpressions = AST__namespace.getNestedCallExpressions(useStateInput);
624
+ const hasFunctionCall = nestedCallExpressions.some((n) => {
625
+ return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
626
+ });
627
+ const hasNewCall = AST__namespace.getNestedNewExpressions(useStateInput).some((n) => {
628
+ return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
629
+ });
630
+ if (!hasFunctionCall && !hasNewCall) {
631
+ return;
632
+ }
633
+ context.report({
634
+ messageId: "preferUseStateLazyInitialization",
635
+ node: useStateInput
636
+ });
637
+ }
638
+ };
639
+ }
640
640
 
641
641
  // src/plugin.ts
642
642
  var plugin = {
package/dist/index.mjs CHANGED
@@ -27,7 +27,7 @@ var rules = {
27
27
 
28
28
  // package.json
29
29
  var name2 = "eslint-plugin-react-hooks-extra";
30
- var version = "1.33.0";
30
+ var version = "1.34.0-beta.1";
31
31
  var createRule = createRuleForPlugin("hooks-extra");
32
32
  function isFromHookCall(context, name3, settings, predicate = constTrue) {
33
33
  const hookAlias = settings.additionalHooks[name3] ?? [];
@@ -308,17 +308,18 @@ var no_direct_set_state_in_use_effect_default = createRule({
308
308
  schema: []
309
309
  },
310
310
  name: RULE_NAME,
311
- create(context) {
312
- if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
313
- return useNoDirectSetStateInUseEffect(context, {
314
- onViolation(ctx, node, data) {
315
- ctx.report({ messageId: "noDirectSetStateInUseEffect", node, data });
316
- },
317
- useEffectKind: "useEffect"
318
- });
319
- },
311
+ create,
320
312
  defaultOptions: []
321
313
  });
314
+ function create(context) {
315
+ if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
316
+ return useNoDirectSetStateInUseEffect(context, {
317
+ onViolation(ctx, node, data) {
318
+ ctx.report({ messageId: "noDirectSetStateInUseEffect", node, data });
319
+ },
320
+ useEffectKind: "useEffect"
321
+ });
322
+ }
322
323
 
323
324
  // src/rules/no-direct-set-state-in-use-layout-effect.ts
324
325
  var RULE_NAME2 = "no-direct-set-state-in-use-layout-effect";
@@ -338,17 +339,18 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
338
339
  schema: []
339
340
  },
340
341
  name: RULE_NAME2,
341
- create(context) {
342
- if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
343
- return useNoDirectSetStateInUseEffect(context, {
344
- onViolation(ctx, node, data) {
345
- ctx.report({ messageId: "noDirectSetStateInUseLayoutEffect", node, data });
346
- },
347
- useEffectKind: "useLayoutEffect"
348
- });
349
- },
342
+ create: create2,
350
343
  defaultOptions: []
351
344
  });
345
+ function create2(context) {
346
+ if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
347
+ return useNoDirectSetStateInUseEffect(context, {
348
+ onViolation(ctx, node, data) {
349
+ ctx.report({ messageId: "noDirectSetStateInUseLayoutEffect", node, data });
350
+ },
351
+ useEffectKind: "useLayoutEffect"
352
+ });
353
+ }
352
354
  var RULE_NAME3 = "no-unnecessary-use-callback";
353
355
  var RULE_FEATURES3 = [
354
356
  "CHK"
@@ -366,68 +368,67 @@ var no_unnecessary_use_callback_default = createRule({
366
368
  schema: []
367
369
  },
368
370
  name: RULE_NAME3,
369
- create(context) {
370
- if (!context.sourceCode.text.includes("use")) {
371
- return {};
372
- }
373
- const alias = getSettingsFromContext(context).additionalHooks.useCallback ?? [];
374
- return {
375
- CallExpression(node) {
376
- if (!isReactHookCall(node)) {
377
- return;
378
- }
379
- const initialScope = context.sourceCode.getScope(node);
380
- if (!isUseCallbackCall(context, node) && !alias.some(isReactHookCallWithNameLoose(node))) {
381
- return;
382
- }
383
- const scope = context.sourceCode.getScope(node);
384
- const component = scope.block;
385
- if (!AST.isFunction(component)) {
386
- return;
387
- }
388
- const [arg0, arg1] = node.arguments;
389
- if (arg0 == null || arg1 == null) {
390
- return;
371
+ create: create3,
372
+ defaultOptions: []
373
+ });
374
+ function create3(context) {
375
+ if (!context.sourceCode.text.includes("use")) return {};
376
+ const alias = getSettingsFromContext(context).additionalHooks.useCallback ?? [];
377
+ return {
378
+ CallExpression(node) {
379
+ if (!isReactHookCall(node)) {
380
+ return;
381
+ }
382
+ const initialScope = context.sourceCode.getScope(node);
383
+ if (!isUseCallbackCall(context, node) && !alias.some(isReactHookCallWithNameLoose(node))) {
384
+ return;
385
+ }
386
+ const scope = context.sourceCode.getScope(node);
387
+ const component = scope.block;
388
+ if (!AST.isFunction(component)) {
389
+ return;
390
+ }
391
+ const [arg0, arg1] = node.arguments;
392
+ if (arg0 == null || arg1 == null) {
393
+ return;
394
+ }
395
+ const hasEmptyDeps = match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
396
+ const variable = VAR4.findVariable(n.name, initialScope);
397
+ const variableNode = VAR4.getVariableInitNode(variable, 0);
398
+ if (variableNode?.type !== AST_NODE_TYPES.ArrayExpression) {
399
+ return false;
391
400
  }
392
- const hasEmptyDeps = match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
393
- const variable = VAR4.findVariable(n.name, initialScope);
394
- const variableNode = VAR4.getVariableInitNode(variable, 0);
395
- if (variableNode?.type !== AST_NODE_TYPES.ArrayExpression) {
396
- return false;
397
- }
398
- return variableNode.elements.length === 0;
399
- }).otherwise(() => false);
400
- if (!hasEmptyDeps) {
401
- return;
401
+ return variableNode.elements.length === 0;
402
+ }).otherwise(() => false);
403
+ if (!hasEmptyDeps) {
404
+ return;
405
+ }
406
+ const arg0Node = match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
407
+ if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) {
408
+ return n.body;
402
409
  }
403
- const arg0Node = match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
404
- if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) {
405
- return n.body;
406
- }
407
- return n;
408
- }).with({ type: AST_NODE_TYPES.FunctionExpression }, identity).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
409
- const variable = VAR4.findVariable(n.name, initialScope);
410
- const variableNode = VAR4.getVariableInitNode(variable, 0);
411
- if (variableNode?.type !== AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== AST_NODE_TYPES.FunctionExpression) {
412
- return _;
413
- }
414
- return variableNode;
415
- }).otherwise(() => _);
416
- if (arg0Node == null) return;
417
- const arg0NodeScope = context.sourceCode.getScope(arg0Node);
418
- const arg0NodeReferences = VAR4.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
419
- const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
420
- if (!isReferencedToComponentScope) {
421
- context.report({
422
- messageId: "noUnnecessaryUseCallback",
423
- node
424
- });
410
+ return n;
411
+ }).with({ type: AST_NODE_TYPES.FunctionExpression }, identity).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
412
+ const variable = VAR4.findVariable(n.name, initialScope);
413
+ const variableNode = VAR4.getVariableInitNode(variable, 0);
414
+ if (variableNode?.type !== AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== AST_NODE_TYPES.FunctionExpression) {
415
+ return _;
425
416
  }
417
+ return variableNode;
418
+ }).otherwise(() => _);
419
+ if (arg0Node == null) return;
420
+ const arg0NodeScope = context.sourceCode.getScope(arg0Node);
421
+ const arg0NodeReferences = VAR4.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
422
+ const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
423
+ if (!isReferencedToComponentScope) {
424
+ context.report({
425
+ messageId: "noUnnecessaryUseCallback",
426
+ node
427
+ });
426
428
  }
427
- };
428
- },
429
- defaultOptions: []
430
- });
429
+ }
430
+ };
431
+ }
431
432
  var RULE_NAME4 = "no-unnecessary-use-memo";
432
433
  var RULE_FEATURES4 = [
433
434
  "CHK"
@@ -445,72 +446,71 @@ var no_unnecessary_use_memo_default = createRule({
445
446
  schema: []
446
447
  },
447
448
  name: RULE_NAME4,
448
- create(context) {
449
- if (!context.sourceCode.text.includes("use")) {
450
- return {};
451
- }
452
- const alias = getSettingsFromContext(context).additionalHooks.useMemo ?? [];
453
- return {
454
- CallExpression(node) {
455
- if (!isReactHookCall(node)) {
456
- return;
457
- }
458
- const initialScope = context.sourceCode.getScope(node);
459
- if (!isUseMemoCall(context, node) && !alias.some(isReactHookCallWithNameLoose(node))) {
460
- return;
461
- }
462
- const scope = context.sourceCode.getScope(node);
463
- const component = scope.block;
464
- if (!AST.isFunction(component)) {
465
- return;
466
- }
467
- const [arg0, arg1] = node.arguments;
468
- if (arg0 == null || arg1 == null) {
469
- return;
470
- }
471
- const hasCallInArg0 = AST.isFunction(arg0) && [...AST.getNestedCallExpressions(arg0.body), ...AST.getNestedNewExpressions(arg0.body)].length > 0;
472
- if (hasCallInArg0) {
473
- return;
449
+ create: create4,
450
+ defaultOptions: []
451
+ });
452
+ function create4(context) {
453
+ if (!context.sourceCode.text.includes("use")) return {};
454
+ const alias = getSettingsFromContext(context).additionalHooks.useMemo ?? [];
455
+ return {
456
+ CallExpression(node) {
457
+ if (!isReactHookCall(node)) {
458
+ return;
459
+ }
460
+ const initialScope = context.sourceCode.getScope(node);
461
+ if (!isUseMemoCall(context, node) && !alias.some(isReactHookCallWithNameLoose(node))) {
462
+ return;
463
+ }
464
+ const scope = context.sourceCode.getScope(node);
465
+ const component = scope.block;
466
+ if (!AST.isFunction(component)) {
467
+ return;
468
+ }
469
+ const [arg0, arg1] = node.arguments;
470
+ if (arg0 == null || arg1 == null) {
471
+ return;
472
+ }
473
+ const hasCallInArg0 = AST.isFunction(arg0) && [...AST.getNestedCallExpressions(arg0.body), ...AST.getNestedNewExpressions(arg0.body)].length > 0;
474
+ if (hasCallInArg0) {
475
+ return;
476
+ }
477
+ const hasEmptyDeps = match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
478
+ const variable = VAR4.findVariable(n.name, initialScope);
479
+ const variableNode = VAR4.getVariableInitNode(variable, 0);
480
+ if (variableNode?.type !== AST_NODE_TYPES.ArrayExpression) {
481
+ return false;
474
482
  }
475
- const hasEmptyDeps = match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
476
- const variable = VAR4.findVariable(n.name, initialScope);
477
- const variableNode = VAR4.getVariableInitNode(variable, 0);
478
- if (variableNode?.type !== AST_NODE_TYPES.ArrayExpression) {
479
- return false;
480
- }
481
- return variableNode.elements.length === 0;
482
- }).otherwise(() => false);
483
- if (!hasEmptyDeps) {
484
- return;
483
+ return variableNode.elements.length === 0;
484
+ }).otherwise(() => false);
485
+ if (!hasEmptyDeps) {
486
+ return;
487
+ }
488
+ const arg0Node = match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
489
+ if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) {
490
+ return n.body;
485
491
  }
486
- const arg0Node = match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
487
- if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) {
488
- return n.body;
489
- }
490
- return n;
491
- }).with({ type: AST_NODE_TYPES.FunctionExpression }, identity).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
492
- const variable = VAR4.findVariable(n.name, initialScope);
493
- const variableNode = VAR4.getVariableInitNode(variable, 0);
494
- if (variableNode?.type !== AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== AST_NODE_TYPES.FunctionExpression) {
495
- return _;
496
- }
497
- return variableNode;
498
- }).otherwise(() => _);
499
- if (arg0Node == null) return;
500
- const arg0NodeScope = context.sourceCode.getScope(arg0Node);
501
- const arg0NodeReferences = VAR4.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
502
- const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
503
- if (!isReferencedToComponentScope) {
504
- context.report({
505
- messageId: "noUnnecessaryUseMemo",
506
- node
507
- });
492
+ return n;
493
+ }).with({ type: AST_NODE_TYPES.FunctionExpression }, identity).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
494
+ const variable = VAR4.findVariable(n.name, initialScope);
495
+ const variableNode = VAR4.getVariableInitNode(variable, 0);
496
+ if (variableNode?.type !== AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== AST_NODE_TYPES.FunctionExpression) {
497
+ return _;
508
498
  }
499
+ return variableNode;
500
+ }).otherwise(() => _);
501
+ if (arg0Node == null) return;
502
+ const arg0NodeScope = context.sourceCode.getScope(arg0Node);
503
+ const arg0NodeReferences = VAR4.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
504
+ const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
505
+ if (!isReferencedToComponentScope) {
506
+ context.report({
507
+ messageId: "noUnnecessaryUseMemo",
508
+ node
509
+ });
509
510
  }
510
- };
511
- },
512
- defaultOptions: []
513
- });
511
+ }
512
+ };
513
+ }
514
514
  var RULE_NAME5 = "no-useless-custom-hooks";
515
515
  var RULE_FEATURES5 = [
516
516
  "CHK"
@@ -531,35 +531,36 @@ var no_useless_custom_hooks_default = createRule({
531
531
  schema: []
532
532
  },
533
533
  name: RULE_NAME5,
534
- create(context) {
535
- const { ctx, listeners } = useHookCollector();
536
- return {
537
- ...listeners,
538
- "Program:exit"(node) {
539
- const allHooks = ctx.getAllHooks(node);
540
- for (const { name: name3, node: node2, hookCalls } of allHooks.values()) {
541
- if (AST.isEmptyFunction(node2)) {
542
- continue;
543
- }
544
- if (hookCalls.length > 0) {
545
- continue;
546
- }
547
- if (isNodeContainsUseCallComments(context, node2)) {
548
- continue;
549
- }
550
- context.report({
551
- messageId: "noUselessCustomHooks",
552
- node: node2,
553
- data: {
554
- name: name3
555
- }
556
- });
557
- }
558
- }
559
- };
560
- },
534
+ create: create5,
561
535
  defaultOptions: []
562
536
  });
537
+ function create5(context) {
538
+ const { ctx, listeners } = useHookCollector();
539
+ return {
540
+ ...listeners,
541
+ "Program:exit"(node) {
542
+ const allHooks = ctx.getAllHooks(node);
543
+ for (const { name: name3, node: node2, hookCalls } of allHooks.values()) {
544
+ if (AST.isEmptyFunction(node2)) {
545
+ continue;
546
+ }
547
+ if (hookCalls.length > 0) {
548
+ continue;
549
+ }
550
+ if (isNodeContainsUseCallComments(context, node2)) {
551
+ continue;
552
+ }
553
+ context.report({
554
+ messageId: "noUselessCustomHooks",
555
+ node: node2,
556
+ data: {
557
+ name: name3
558
+ }
559
+ });
560
+ }
561
+ }
562
+ };
563
+ }
563
564
  var RULE_NAME6 = "prefer-use-state-lazy-initialization";
564
565
  var RULE_FEATURES6 = [
565
566
  "CHK"
@@ -578,42 +579,41 @@ var prefer_use_state_lazy_initialization_default = createRule({
578
579
  schema: []
579
580
  },
580
581
  name: RULE_NAME6,
581
- create(context) {
582
- if (!context.sourceCode.text.includes("use")) {
583
- return {};
584
- }
585
- const alias = getSettingsFromContext(context).additionalHooks.useState ?? [];
586
- return {
587
- CallExpression(node) {
588
- if (!isReactHookCall(node)) {
589
- return;
590
- }
591
- if (!isUseStateCall(context, node) && !alias.some(isReactHookCallWithNameLoose(node))) {
592
- return;
593
- }
594
- const [useStateInput] = node.arguments;
595
- if (useStateInput == null) {
596
- return;
597
- }
598
- const nestedCallExpressions = AST.getNestedCallExpressions(useStateInput);
599
- const hasFunctionCall = nestedCallExpressions.some((n) => {
600
- return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
601
- });
602
- const hasNewCall = AST.getNestedNewExpressions(useStateInput).some((n) => {
603
- return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
604
- });
605
- if (!hasFunctionCall && !hasNewCall) {
606
- return;
607
- }
608
- context.report({
609
- messageId: "preferUseStateLazyInitialization",
610
- node: useStateInput
611
- });
612
- }
613
- };
614
- },
582
+ create: create6,
615
583
  defaultOptions: []
616
584
  });
585
+ function create6(context) {
586
+ if (!context.sourceCode.text.includes("use")) return {};
587
+ const alias = getSettingsFromContext(context).additionalHooks.useState ?? [];
588
+ return {
589
+ CallExpression(node) {
590
+ if (!isReactHookCall(node)) {
591
+ return;
592
+ }
593
+ if (!isUseStateCall(context, node) && !alias.some(isReactHookCallWithNameLoose(node))) {
594
+ return;
595
+ }
596
+ const [useStateInput] = node.arguments;
597
+ if (useStateInput == null) {
598
+ return;
599
+ }
600
+ const nestedCallExpressions = AST.getNestedCallExpressions(useStateInput);
601
+ const hasFunctionCall = nestedCallExpressions.some((n) => {
602
+ return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
603
+ });
604
+ const hasNewCall = AST.getNestedNewExpressions(useStateInput).some((n) => {
605
+ return "name" in n.callee && !ALLOW_LIST.includes(n.callee.name);
606
+ });
607
+ if (!hasFunctionCall && !hasNewCall) {
608
+ return;
609
+ }
610
+ context.report({
611
+ messageId: "preferUseStateLazyInitialization",
612
+ node: useStateInput
613
+ });
614
+ }
615
+ };
616
+ }
617
617
 
618
618
  // src/plugin.ts
619
619
  var plugin = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-hooks-extra",
3
- "version": "1.33.0",
3
+ "version": "1.34.0-beta.1",
4
4
  "description": "ESLint React's ESLint plugin for React Hooks related rules.",
5
5
  "keywords": [
6
6
  "react",
@@ -50,12 +50,12 @@
50
50
  "@typescript-eslint/utils": "^8.26.1",
51
51
  "string-ts": "^2.2.1",
52
52
  "ts-pattern": "^5.6.2",
53
- "@eslint-react/ast": "1.33.0",
54
- "@eslint-react/core": "1.33.0",
55
- "@eslint-react/jsx": "1.33.0",
56
- "@eslint-react/eff": "1.33.0",
57
- "@eslint-react/shared": "1.33.0",
58
- "@eslint-react/var": "1.33.0"
53
+ "@eslint-react/shared": "1.34.0-beta.1",
54
+ "@eslint-react/var": "1.34.0-beta.1",
55
+ "@eslint-react/ast": "1.34.0-beta.1",
56
+ "@eslint-react/eff": "1.34.0-beta.1",
57
+ "@eslint-react/core": "1.34.0-beta.1",
58
+ "@eslint-react/jsx": "1.34.0-beta.1"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@types/react": "^19.0.10",