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