eslint-plugin-react-hooks-extra 1.6.1-next.1 → 1.6.1-next.3
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 +108 -169
- package/dist/index.mjs +109 -170
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -9,44 +9,22 @@ var astUtils = require('@typescript-eslint/utils/ast-utils');
|
|
|
9
9
|
|
|
10
10
|
// package.json
|
|
11
11
|
var name = "eslint-plugin-react-hooks-extra";
|
|
12
|
-
var version = "1.6.1-next.
|
|
12
|
+
var version = "1.6.1-next.3";
|
|
13
13
|
var createRule = shared.createRuleForPlugin("hooks-extra");
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
name: RULE_NAME,
|
|
29
|
-
create(context) {
|
|
30
|
-
const { ctx, listeners } = core.useHookCollector();
|
|
31
|
-
return {
|
|
32
|
-
...listeners,
|
|
33
|
-
"Program:exit"(node) {
|
|
34
|
-
const allHooks = ctx.getAllHooks(node);
|
|
35
|
-
for (const { name: name2, hookCalls, node: node2 } of allHooks.values()) {
|
|
36
|
-
if (hookCalls.length > 0) continue;
|
|
37
|
-
context.report({
|
|
38
|
-
data: {
|
|
39
|
-
name: name2.value
|
|
40
|
-
},
|
|
41
|
-
messageId: "ENSURE_CUSTOM_HOOKS_USING_OTHER_HOOKS",
|
|
42
|
-
node: node2
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
},
|
|
48
|
-
defaultOptions: []
|
|
49
|
-
});
|
|
14
|
+
function isFromUseStateCall(context, useStateAlias) {
|
|
15
|
+
return (topLevelId) => {
|
|
16
|
+
const useStateCall = tools.F.pipe(
|
|
17
|
+
_var.findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
|
|
18
|
+
tools.O.flatMap(_var.getVariableNode(0)),
|
|
19
|
+
tools.O.filter(ast.is(ast.NodeType.CallExpression)),
|
|
20
|
+
tools.O.filter(core.isReactHookCallWithNameAlias("useState", context, useStateAlias))
|
|
21
|
+
);
|
|
22
|
+
if (tools.O.isNone(useStateCall)) return false;
|
|
23
|
+
const { parent } = useStateCall.value;
|
|
24
|
+
if (!("id" in parent && parent.id?.type === ast.NodeType.ArrayPattern)) return true;
|
|
25
|
+
return parent.id.elements.findIndex((e2) => e2?.type === ast.NodeType.Identifier && e2.name === topLevelId.name) === 1;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
50
28
|
|
|
51
29
|
// ../../../node_modules/.pnpm/ts-pattern@5.2.0/node_modules/ts-pattern/dist/index.js
|
|
52
30
|
var t = Symbol.for("@ts-pattern/matcher");
|
|
@@ -231,7 +209,74 @@ var z = class _z {
|
|
|
231
209
|
}
|
|
232
210
|
};
|
|
233
211
|
|
|
234
|
-
// src/
|
|
212
|
+
// src/utils/is-set-state-call.ts
|
|
213
|
+
function isSetStateCall(context, useStateAlias) {
|
|
214
|
+
return (node) => {
|
|
215
|
+
const topLevelId = $(node.callee).with({ type: ast.NodeType.Identifier }, tools.O.some).with({ type: ast.NodeType.MemberExpression }, (n2) => {
|
|
216
|
+
if (!("name" in n2.object)) return tools.O.none();
|
|
217
|
+
const initialScope = context.sourceCode.getScope(n2);
|
|
218
|
+
const property = astUtils.getStaticValue(n2.property, initialScope);
|
|
219
|
+
if (property?.value === 1) return tools.O.fromNullable(n2.object);
|
|
220
|
+
return tools.O.none();
|
|
221
|
+
}).with({ type: ast.NodeType.CallExpression }, (n2) => {
|
|
222
|
+
if (!ast.is(ast.NodeType.MemberExpression)(n2.callee)) return tools.O.none();
|
|
223
|
+
if (!("name" in n2.callee.object)) return tools.O.none();
|
|
224
|
+
const isAt = a({
|
|
225
|
+
type: ast.NodeType.MemberExpression,
|
|
226
|
+
property: {
|
|
227
|
+
type: ast.NodeType.Identifier,
|
|
228
|
+
name: "at"
|
|
229
|
+
}
|
|
230
|
+
}, n2.callee);
|
|
231
|
+
const [index] = n2.arguments;
|
|
232
|
+
if (!isAt || !index) return tools.O.none();
|
|
233
|
+
const initialScope = context.sourceCode.getScope(n2);
|
|
234
|
+
const value = astUtils.getStaticValue(index, initialScope);
|
|
235
|
+
if (value?.value === 1) return tools.O.fromNullable(n2.callee.object);
|
|
236
|
+
return tools.O.none();
|
|
237
|
+
}).otherwise(tools.O.none);
|
|
238
|
+
return tools.O.exists(topLevelId, isFromUseStateCall(context, useStateAlias));
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function isThenCall(node) {
|
|
242
|
+
return node.callee.type === ast.NodeType.MemberExpression && node.callee.property.type === ast.NodeType.Identifier && node.callee.property.name === "then";
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// src/rules/ensure-custom-hooks-using-other-hooks.ts
|
|
246
|
+
var RULE_NAME = "ensure-custom-hooks-using-other-hooks";
|
|
247
|
+
var ensure_custom_hooks_using_other_hooks_default = createRule({
|
|
248
|
+
meta: {
|
|
249
|
+
type: "problem",
|
|
250
|
+
docs: {
|
|
251
|
+
description: "enforce custom hooks using other hooks"
|
|
252
|
+
},
|
|
253
|
+
messages: {
|
|
254
|
+
ENSURE_CUSTOM_HOOKS_USING_OTHER_HOOKS: "A custom hook '{{name}}' should use other hooks."
|
|
255
|
+
},
|
|
256
|
+
schema: []
|
|
257
|
+
},
|
|
258
|
+
name: RULE_NAME,
|
|
259
|
+
create(context) {
|
|
260
|
+
const { ctx, listeners } = core.useHookCollector();
|
|
261
|
+
return {
|
|
262
|
+
...listeners,
|
|
263
|
+
"Program:exit"(node) {
|
|
264
|
+
const allHooks = ctx.getAllHooks(node);
|
|
265
|
+
for (const { name: name2, hookCalls, node: node2 } of allHooks.values()) {
|
|
266
|
+
if (hookCalls.length > 0) continue;
|
|
267
|
+
context.report({
|
|
268
|
+
data: {
|
|
269
|
+
name: name2.value
|
|
270
|
+
},
|
|
271
|
+
messageId: "ENSURE_CUSTOM_HOOKS_USING_OTHER_HOOKS",
|
|
272
|
+
node: node2
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
},
|
|
278
|
+
defaultOptions: []
|
|
279
|
+
});
|
|
235
280
|
var RULE_NAME2 = "ensure-use-callback-has-non-empty-deps";
|
|
236
281
|
var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
237
282
|
meta: {
|
|
@@ -251,7 +296,7 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
251
296
|
CallExpression(node) {
|
|
252
297
|
if (!core.isReactHookCall(node)) return;
|
|
253
298
|
const initialScope = context.sourceCode.getScope(node);
|
|
254
|
-
if (!core.isUseCallbackCall(node, context) && !alias.some(
|
|
299
|
+
if (!core.isUseCallbackCall(node, context) && !alias.some(core.isReactHookCallWithNameLoose(node))) {
|
|
255
300
|
return;
|
|
256
301
|
}
|
|
257
302
|
const scope = context.sourceCode.getScope(node);
|
|
@@ -329,7 +374,7 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
329
374
|
CallExpression(node) {
|
|
330
375
|
if (!core.isReactHookCall(node)) return;
|
|
331
376
|
const initialScope = context.sourceCode.getScope(node);
|
|
332
|
-
if (!core.isUseMemoCall(node, context) && !alias.some(
|
|
377
|
+
if (!core.isUseMemoCall(node, context) && !alias.some(core.isReactHookCallWithNameLoose(node))) {
|
|
333
378
|
return;
|
|
334
379
|
}
|
|
335
380
|
const scope = context.sourceCode.getScope(node);
|
|
@@ -389,6 +434,15 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
389
434
|
defaultOptions: []
|
|
390
435
|
});
|
|
391
436
|
var RULE_NAME4 = "no-direct-set-state-in-use-effect";
|
|
437
|
+
function isEffectFunction(context, useSomeEffectAlias) {
|
|
438
|
+
return (node) => node.parent?.type === ast.NodeType.CallExpression && node.parent.callee !== node && core.isReactHookCallWithNameAlias("useEffect", context, useSomeEffectAlias)(node.parent);
|
|
439
|
+
}
|
|
440
|
+
function getCallKind(node, context, useStateAlias, useEffectAlias) {
|
|
441
|
+
return $(node).when(isThenCall, () => "then").when(isSetStateCall(context, useStateAlias), () => "setState").when(core.isReactHookCallWithNameAlias("useState", context, useStateAlias), () => "useState").when(core.isReactHookCallWithNameAlias("useEffect", context, useEffectAlias), () => "useEffect").otherwise(() => "other");
|
|
442
|
+
}
|
|
443
|
+
function getFunctionKind(node, context, useEffectAlias) {
|
|
444
|
+
return $(node).when(isEffectFunction(context, useEffectAlias), () => "effect").when(ast.isIIFE, () => "immediate").otherwise(() => "other");
|
|
445
|
+
}
|
|
392
446
|
var no_direct_set_state_in_use_effect_default = createRule({
|
|
393
447
|
meta: {
|
|
394
448
|
type: "problem",
|
|
@@ -404,68 +458,6 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
404
458
|
create(context) {
|
|
405
459
|
const settings = shared.decodeSettings(context.settings);
|
|
406
460
|
const { useEffect: useEffectAlias = [], useState: useStateAlias = [] } = settings.additionalHooks ?? {};
|
|
407
|
-
function isUseEffectCallWithAlias(node) {
|
|
408
|
-
return core.isUseEffectCall(node, context) || useEffectAlias.some(tools.F.flip(core.isReactHookCallWithNameLoose)(node));
|
|
409
|
-
}
|
|
410
|
-
function isUseStateCallWithAlias(node) {
|
|
411
|
-
return core.isUseStateCall(node, context) || useStateAlias.some(tools.F.flip(core.isReactHookCallWithNameLoose)(node));
|
|
412
|
-
}
|
|
413
|
-
function isEffectFunction(node) {
|
|
414
|
-
return node.parent?.type === ast.NodeType.CallExpression && node.parent.callee !== node && isUseEffectCallWithAlias(node.parent);
|
|
415
|
-
}
|
|
416
|
-
function isCleanUpFunction(_2) {
|
|
417
|
-
}
|
|
418
|
-
function isFromUseStateCall(topLevelId) {
|
|
419
|
-
const useStateCall = tools.F.pipe(
|
|
420
|
-
_var.findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
|
|
421
|
-
tools.O.flatMap(_var.getVariableNode(0)),
|
|
422
|
-
tools.O.filter(ast.is(ast.NodeType.CallExpression)),
|
|
423
|
-
tools.O.filter(isUseStateCallWithAlias)
|
|
424
|
-
);
|
|
425
|
-
if (tools.O.isNone(useStateCall)) return false;
|
|
426
|
-
const { parent } = useStateCall.value;
|
|
427
|
-
if (!a({ id: { type: ast.NodeType.ArrayPattern }, type: ast.NodeType.VariableDeclarator }, parent)) return true;
|
|
428
|
-
return parent.id.elements.findIndex((e2) => e2?.type === ast.NodeType.Identifier && e2.name === topLevelId.name) === 1;
|
|
429
|
-
}
|
|
430
|
-
function isSetStateCall(node) {
|
|
431
|
-
const topLevelId = $(node.callee).with({ type: ast.NodeType.Identifier }, tools.O.some).with({ type: ast.NodeType.MemberExpression }, (n2) => {
|
|
432
|
-
if (!("name" in n2.object)) return tools.O.none();
|
|
433
|
-
const initialScope = context.sourceCode.getScope(n2);
|
|
434
|
-
const property = astUtils.getStaticValue(n2.property, initialScope);
|
|
435
|
-
if (property?.value === 1) return tools.O.fromNullable(n2.object);
|
|
436
|
-
return tools.O.none();
|
|
437
|
-
}).with({ type: ast.NodeType.CallExpression }, (n2) => {
|
|
438
|
-
if (!ast.is(ast.NodeType.MemberExpression)(n2.callee)) return tools.O.none();
|
|
439
|
-
if (!("name" in n2.callee.object)) return tools.O.none();
|
|
440
|
-
const isAt = a({
|
|
441
|
-
type: ast.NodeType.MemberExpression,
|
|
442
|
-
property: {
|
|
443
|
-
type: ast.NodeType.Identifier,
|
|
444
|
-
name: "at"
|
|
445
|
-
}
|
|
446
|
-
}, n2.callee);
|
|
447
|
-
const [index] = n2.arguments;
|
|
448
|
-
if (!isAt || !index) return tools.O.none();
|
|
449
|
-
const initialScope = context.sourceCode.getScope(n2);
|
|
450
|
-
const value = astUtils.getStaticValue(index, initialScope);
|
|
451
|
-
if (value?.value === 1) return tools.O.fromNullable(n2.callee.object);
|
|
452
|
-
return tools.O.none();
|
|
453
|
-
}).otherwise(tools.O.none);
|
|
454
|
-
return tools.O.exists(topLevelId, isFromUseStateCall);
|
|
455
|
-
}
|
|
456
|
-
function isThenCall(node) {
|
|
457
|
-
if (node.callee.type !== ast.NodeType.MemberExpression) return false;
|
|
458
|
-
return a({
|
|
459
|
-
type: ast.NodeType.Identifier,
|
|
460
|
-
name: "then"
|
|
461
|
-
}, node.callee.property);
|
|
462
|
-
}
|
|
463
|
-
function getCallKind(node) {
|
|
464
|
-
return $(node).when(isThenCall, () => "then").when(isSetStateCall, () => "setState").when(isUseStateCallWithAlias, () => "useState").when(isUseEffectCallWithAlias, () => "useEffect").otherwise(() => "other");
|
|
465
|
-
}
|
|
466
|
-
function getFunctionKind(node) {
|
|
467
|
-
return $(node).when(isEffectFunction, () => "effect").when(isCleanUpFunction, () => "cleanup").when(ast.isIIFE, () => "immediate").otherwise(() => "other");
|
|
468
|
-
}
|
|
469
461
|
const functionStack = tools.MutList.make();
|
|
470
462
|
const effectFunctionRef = tools.MutRef.make(null);
|
|
471
463
|
const effectFunctionIdentifiers = [];
|
|
@@ -479,7 +471,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
479
471
|
};
|
|
480
472
|
return {
|
|
481
473
|
":function"(node) {
|
|
482
|
-
const functionKind = getFunctionKind(node);
|
|
474
|
+
const functionKind = getFunctionKind(node, context, useEffectAlias);
|
|
483
475
|
tools.MutList.append(functionStack, [node, functionKind]);
|
|
484
476
|
$(functionKind).with("effect", () => {
|
|
485
477
|
onEffectFunctionEnter(node);
|
|
@@ -493,7 +485,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
493
485
|
const effectFn = tools.MutRef.get(effectFunctionRef);
|
|
494
486
|
const [parentFn, parentFnKind] = tools.MutList.tail(functionStack) ?? [];
|
|
495
487
|
if (parentFn?.async) return;
|
|
496
|
-
const callKind = getCallKind(node);
|
|
488
|
+
const callKind = getCallKind(node, context, useStateAlias, useEffectAlias);
|
|
497
489
|
$(callKind).with("setState", () => {
|
|
498
490
|
if (!parentFn) return;
|
|
499
491
|
if (parentFn !== effectFn && parentFnKind !== "immediate") {
|
|
@@ -553,6 +545,15 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
553
545
|
defaultOptions: []
|
|
554
546
|
});
|
|
555
547
|
var RULE_NAME5 = "no-direct-set-state-in-use-layout-effect";
|
|
548
|
+
function isLayoutEffectFunction(context, useSomeEffectAlias) {
|
|
549
|
+
return (node) => node.parent?.type === ast.NodeType.CallExpression && node.parent.callee !== node && core.isReactHookCallWithNameAlias("useLayoutEffect", context, useSomeEffectAlias)(node.parent);
|
|
550
|
+
}
|
|
551
|
+
function getCallKind2(node, context, useStateAlias, useLayoutEffectAlias) {
|
|
552
|
+
return $(node).when(isThenCall, () => "then").when(isSetStateCall(context, useStateAlias), () => "setState").when(core.isReactHookCallWithNameAlias("useState", context, useStateAlias), () => "useState").when(core.isReactHookCallWithNameAlias("useLayoutEffect", context, useLayoutEffectAlias), () => "useLayoutEffect").otherwise(() => "other");
|
|
553
|
+
}
|
|
554
|
+
function getFunctionKind2(node, context, useLayoutEffectAlias) {
|
|
555
|
+
return $(node).when(isLayoutEffectFunction(context, useLayoutEffectAlias), () => "effect").when(ast.isIIFE, () => "immediate").otherwise(() => "other");
|
|
556
|
+
}
|
|
556
557
|
var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
557
558
|
meta: {
|
|
558
559
|
type: "problem",
|
|
@@ -568,68 +569,6 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
568
569
|
create(context) {
|
|
569
570
|
const settings = shared.decodeSettings(context.settings);
|
|
570
571
|
const { useLayoutEffect: useLayoutEffectAlias = [], useState: useStateAlias = [] } = settings.additionalHooks ?? {};
|
|
571
|
-
function isUseLayoutEffectCallWithAlias(node) {
|
|
572
|
-
return core.isUseLayoutEffectCall(node, context) || useLayoutEffectAlias.some(tools.F.flip(core.isReactHookCallWithNameLoose)(node));
|
|
573
|
-
}
|
|
574
|
-
function isUseStateCallWithAlias(node) {
|
|
575
|
-
return core.isUseStateCall(node, context) || useStateAlias.some(tools.F.flip(core.isReactHookCallWithNameLoose)(node));
|
|
576
|
-
}
|
|
577
|
-
function isEffectFunction(node) {
|
|
578
|
-
return node.parent?.type === ast.NodeType.CallExpression && node.parent.callee !== node && isUseLayoutEffectCallWithAlias(node.parent);
|
|
579
|
-
}
|
|
580
|
-
function isCleanUpFunction(_2) {
|
|
581
|
-
}
|
|
582
|
-
function isFromUseStateCall(topLevelId) {
|
|
583
|
-
const useStateCall = tools.F.pipe(
|
|
584
|
-
_var.findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
|
|
585
|
-
tools.O.flatMap(_var.getVariableNode(0)),
|
|
586
|
-
tools.O.filter(ast.is(ast.NodeType.CallExpression)),
|
|
587
|
-
tools.O.filter(isUseStateCallWithAlias)
|
|
588
|
-
);
|
|
589
|
-
if (tools.O.isNone(useStateCall)) return false;
|
|
590
|
-
const { parent } = useStateCall.value;
|
|
591
|
-
if (!a({ id: { type: ast.NodeType.ArrayPattern }, type: ast.NodeType.VariableDeclarator }, parent)) return true;
|
|
592
|
-
return parent.id.elements.findIndex((e2) => e2?.type === ast.NodeType.Identifier && e2.name === topLevelId.name) === 1;
|
|
593
|
-
}
|
|
594
|
-
function isSetStateCall(node) {
|
|
595
|
-
const topLevelId = $(node.callee).with({ type: ast.NodeType.Identifier }, tools.O.some).with({ type: ast.NodeType.MemberExpression }, (n2) => {
|
|
596
|
-
if (!("name" in n2.object)) return tools.O.none();
|
|
597
|
-
const initialScope = context.sourceCode.getScope(n2);
|
|
598
|
-
const property = astUtils.getStaticValue(n2.property, initialScope);
|
|
599
|
-
if (property?.value === 1) return tools.O.fromNullable(n2.object);
|
|
600
|
-
return tools.O.none();
|
|
601
|
-
}).with({ type: ast.NodeType.CallExpression }, (n2) => {
|
|
602
|
-
if (!ast.is(ast.NodeType.MemberExpression)(n2.callee)) return tools.O.none();
|
|
603
|
-
if (!("name" in n2.callee.object)) return tools.O.none();
|
|
604
|
-
const isAt = a({
|
|
605
|
-
type: ast.NodeType.MemberExpression,
|
|
606
|
-
property: {
|
|
607
|
-
type: ast.NodeType.Identifier,
|
|
608
|
-
name: "at"
|
|
609
|
-
}
|
|
610
|
-
}, n2.callee);
|
|
611
|
-
const [index] = n2.arguments;
|
|
612
|
-
if (!isAt || !index) return tools.O.none();
|
|
613
|
-
const initialScope = context.sourceCode.getScope(n2);
|
|
614
|
-
const value = astUtils.getStaticValue(index, initialScope);
|
|
615
|
-
if (value?.value === 1) return tools.O.fromNullable(n2.callee.object);
|
|
616
|
-
return tools.O.none();
|
|
617
|
-
}).otherwise(tools.O.none);
|
|
618
|
-
return tools.O.exists(topLevelId, isFromUseStateCall);
|
|
619
|
-
}
|
|
620
|
-
function isThenCall(node) {
|
|
621
|
-
if (node.callee.type !== ast.NodeType.MemberExpression) return false;
|
|
622
|
-
return a({
|
|
623
|
-
type: ast.NodeType.Identifier,
|
|
624
|
-
name: "then"
|
|
625
|
-
}, node.callee.property);
|
|
626
|
-
}
|
|
627
|
-
function getCallKind(node) {
|
|
628
|
-
return $(node).when(isThenCall, () => "then").when(isSetStateCall, () => "setState").when(isUseStateCallWithAlias, () => "useState").when(isUseLayoutEffectCallWithAlias, () => "useLayoutEffect").otherwise(() => "other");
|
|
629
|
-
}
|
|
630
|
-
function getFunctionKind(node) {
|
|
631
|
-
return $(node).when(isEffectFunction, () => "effect").when(isCleanUpFunction, () => "cleanup").when(ast.isIIFE, () => "immediate").otherwise(() => "other");
|
|
632
|
-
}
|
|
633
572
|
const functionStack = tools.MutList.make();
|
|
634
573
|
const effectFunctionRef = tools.MutRef.make(null);
|
|
635
574
|
const effectFunctionIdentifiers = [];
|
|
@@ -643,7 +582,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
643
582
|
};
|
|
644
583
|
return {
|
|
645
584
|
":function"(node) {
|
|
646
|
-
const functionKind =
|
|
585
|
+
const functionKind = getFunctionKind2(node, context, useLayoutEffectAlias);
|
|
647
586
|
tools.MutList.append(functionStack, [node, functionKind]);
|
|
648
587
|
$(functionKind).with("effect", () => {
|
|
649
588
|
onEffectFunctionEnter(node);
|
|
@@ -657,7 +596,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
657
596
|
const effectFn = tools.MutRef.get(effectFunctionRef);
|
|
658
597
|
const [parentFn, parentFnKind] = tools.MutList.tail(functionStack) ?? [];
|
|
659
598
|
if (parentFn?.async) return;
|
|
660
|
-
const callKind =
|
|
599
|
+
const callKind = getCallKind2(node, context, useStateAlias, useLayoutEffectAlias);
|
|
661
600
|
$(callKind).with("setState", () => {
|
|
662
601
|
if (!parentFn) return;
|
|
663
602
|
if (parentFn !== effectFn && parentFnKind !== "immediate") {
|
|
@@ -735,7 +674,7 @@ var prefer_use_state_lazy_initialization_default = createRule({
|
|
|
735
674
|
return {
|
|
736
675
|
CallExpression(node) {
|
|
737
676
|
if (!core.isReactHookCall(node)) return;
|
|
738
|
-
if (!core.isUseStateCall(node, context) && !alias.some(
|
|
677
|
+
if (!core.isUseStateCall(node, context) && !alias.some(core.isReactHookCallWithNameLoose(node))) return;
|
|
739
678
|
const [useStateInput] = node.arguments;
|
|
740
679
|
if (!useStateInput) return;
|
|
741
680
|
const nestedCallExpressions = ast.getNestedCallExpressions(useStateInput);
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useHookCollector, isReactHookCall, isUseCallbackCall, isReactHookCallWithNameLoose, isUseMemoCall, isUseStateCall,
|
|
1
|
+
import { useHookCollector, isReactHookCall, isUseCallbackCall, isReactHookCallWithNameLoose, isUseMemoCall, isUseStateCall, isReactHookCallWithNameAlias } from '@eslint-react/core';
|
|
2
2
|
import { createRuleForPlugin, decodeSettings } from '@eslint-react/shared';
|
|
3
3
|
import { isFunction, NodeType, is, getNestedIdentifiers, getNestedCallExpressions, isIIFE } from '@eslint-react/ast';
|
|
4
4
|
import { F, O, MutList, MutRef } from '@eslint-react/tools';
|
|
@@ -7,44 +7,22 @@ import { getStaticValue } from '@typescript-eslint/utils/ast-utils';
|
|
|
7
7
|
|
|
8
8
|
// package.json
|
|
9
9
|
var name = "eslint-plugin-react-hooks-extra";
|
|
10
|
-
var version = "1.6.1-next.
|
|
10
|
+
var version = "1.6.1-next.3";
|
|
11
11
|
var createRule = createRuleForPlugin("hooks-extra");
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
name: RULE_NAME,
|
|
27
|
-
create(context) {
|
|
28
|
-
const { ctx, listeners } = useHookCollector();
|
|
29
|
-
return {
|
|
30
|
-
...listeners,
|
|
31
|
-
"Program:exit"(node) {
|
|
32
|
-
const allHooks = ctx.getAllHooks(node);
|
|
33
|
-
for (const { name: name2, hookCalls, node: node2 } of allHooks.values()) {
|
|
34
|
-
if (hookCalls.length > 0) continue;
|
|
35
|
-
context.report({
|
|
36
|
-
data: {
|
|
37
|
-
name: name2.value
|
|
38
|
-
},
|
|
39
|
-
messageId: "ENSURE_CUSTOM_HOOKS_USING_OTHER_HOOKS",
|
|
40
|
-
node: node2
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
},
|
|
46
|
-
defaultOptions: []
|
|
47
|
-
});
|
|
12
|
+
function isFromUseStateCall(context, useStateAlias) {
|
|
13
|
+
return (topLevelId) => {
|
|
14
|
+
const useStateCall = F.pipe(
|
|
15
|
+
findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
|
|
16
|
+
O.flatMap(getVariableNode(0)),
|
|
17
|
+
O.filter(is(NodeType.CallExpression)),
|
|
18
|
+
O.filter(isReactHookCallWithNameAlias("useState", context, useStateAlias))
|
|
19
|
+
);
|
|
20
|
+
if (O.isNone(useStateCall)) return false;
|
|
21
|
+
const { parent } = useStateCall.value;
|
|
22
|
+
if (!("id" in parent && parent.id?.type === NodeType.ArrayPattern)) return true;
|
|
23
|
+
return parent.id.elements.findIndex((e2) => e2?.type === NodeType.Identifier && e2.name === topLevelId.name) === 1;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
48
26
|
|
|
49
27
|
// ../../../node_modules/.pnpm/ts-pattern@5.2.0/node_modules/ts-pattern/dist/index.js
|
|
50
28
|
var t = Symbol.for("@ts-pattern/matcher");
|
|
@@ -229,7 +207,74 @@ var z = class _z {
|
|
|
229
207
|
}
|
|
230
208
|
};
|
|
231
209
|
|
|
232
|
-
// src/
|
|
210
|
+
// src/utils/is-set-state-call.ts
|
|
211
|
+
function isSetStateCall(context, useStateAlias) {
|
|
212
|
+
return (node) => {
|
|
213
|
+
const topLevelId = $(node.callee).with({ type: NodeType.Identifier }, O.some).with({ type: NodeType.MemberExpression }, (n2) => {
|
|
214
|
+
if (!("name" in n2.object)) return O.none();
|
|
215
|
+
const initialScope = context.sourceCode.getScope(n2);
|
|
216
|
+
const property = getStaticValue(n2.property, initialScope);
|
|
217
|
+
if (property?.value === 1) return O.fromNullable(n2.object);
|
|
218
|
+
return O.none();
|
|
219
|
+
}).with({ type: NodeType.CallExpression }, (n2) => {
|
|
220
|
+
if (!is(NodeType.MemberExpression)(n2.callee)) return O.none();
|
|
221
|
+
if (!("name" in n2.callee.object)) return O.none();
|
|
222
|
+
const isAt = a({
|
|
223
|
+
type: NodeType.MemberExpression,
|
|
224
|
+
property: {
|
|
225
|
+
type: NodeType.Identifier,
|
|
226
|
+
name: "at"
|
|
227
|
+
}
|
|
228
|
+
}, n2.callee);
|
|
229
|
+
const [index] = n2.arguments;
|
|
230
|
+
if (!isAt || !index) return O.none();
|
|
231
|
+
const initialScope = context.sourceCode.getScope(n2);
|
|
232
|
+
const value = getStaticValue(index, initialScope);
|
|
233
|
+
if (value?.value === 1) return O.fromNullable(n2.callee.object);
|
|
234
|
+
return O.none();
|
|
235
|
+
}).otherwise(O.none);
|
|
236
|
+
return O.exists(topLevelId, isFromUseStateCall(context, useStateAlias));
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function isThenCall(node) {
|
|
240
|
+
return node.callee.type === NodeType.MemberExpression && node.callee.property.type === NodeType.Identifier && node.callee.property.name === "then";
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// src/rules/ensure-custom-hooks-using-other-hooks.ts
|
|
244
|
+
var RULE_NAME = "ensure-custom-hooks-using-other-hooks";
|
|
245
|
+
var ensure_custom_hooks_using_other_hooks_default = createRule({
|
|
246
|
+
meta: {
|
|
247
|
+
type: "problem",
|
|
248
|
+
docs: {
|
|
249
|
+
description: "enforce custom hooks using other hooks"
|
|
250
|
+
},
|
|
251
|
+
messages: {
|
|
252
|
+
ENSURE_CUSTOM_HOOKS_USING_OTHER_HOOKS: "A custom hook '{{name}}' should use other hooks."
|
|
253
|
+
},
|
|
254
|
+
schema: []
|
|
255
|
+
},
|
|
256
|
+
name: RULE_NAME,
|
|
257
|
+
create(context) {
|
|
258
|
+
const { ctx, listeners } = useHookCollector();
|
|
259
|
+
return {
|
|
260
|
+
...listeners,
|
|
261
|
+
"Program:exit"(node) {
|
|
262
|
+
const allHooks = ctx.getAllHooks(node);
|
|
263
|
+
for (const { name: name2, hookCalls, node: node2 } of allHooks.values()) {
|
|
264
|
+
if (hookCalls.length > 0) continue;
|
|
265
|
+
context.report({
|
|
266
|
+
data: {
|
|
267
|
+
name: name2.value
|
|
268
|
+
},
|
|
269
|
+
messageId: "ENSURE_CUSTOM_HOOKS_USING_OTHER_HOOKS",
|
|
270
|
+
node: node2
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
},
|
|
276
|
+
defaultOptions: []
|
|
277
|
+
});
|
|
233
278
|
var RULE_NAME2 = "ensure-use-callback-has-non-empty-deps";
|
|
234
279
|
var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
235
280
|
meta: {
|
|
@@ -249,7 +294,7 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
249
294
|
CallExpression(node) {
|
|
250
295
|
if (!isReactHookCall(node)) return;
|
|
251
296
|
const initialScope = context.sourceCode.getScope(node);
|
|
252
|
-
if (!isUseCallbackCall(node, context) && !alias.some(
|
|
297
|
+
if (!isUseCallbackCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) {
|
|
253
298
|
return;
|
|
254
299
|
}
|
|
255
300
|
const scope = context.sourceCode.getScope(node);
|
|
@@ -327,7 +372,7 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
327
372
|
CallExpression(node) {
|
|
328
373
|
if (!isReactHookCall(node)) return;
|
|
329
374
|
const initialScope = context.sourceCode.getScope(node);
|
|
330
|
-
if (!isUseMemoCall(node, context) && !alias.some(
|
|
375
|
+
if (!isUseMemoCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) {
|
|
331
376
|
return;
|
|
332
377
|
}
|
|
333
378
|
const scope = context.sourceCode.getScope(node);
|
|
@@ -387,6 +432,15 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
387
432
|
defaultOptions: []
|
|
388
433
|
});
|
|
389
434
|
var RULE_NAME4 = "no-direct-set-state-in-use-effect";
|
|
435
|
+
function isEffectFunction(context, useSomeEffectAlias) {
|
|
436
|
+
return (node) => node.parent?.type === NodeType.CallExpression && node.parent.callee !== node && isReactHookCallWithNameAlias("useEffect", context, useSomeEffectAlias)(node.parent);
|
|
437
|
+
}
|
|
438
|
+
function getCallKind(node, context, useStateAlias, useEffectAlias) {
|
|
439
|
+
return $(node).when(isThenCall, () => "then").when(isSetStateCall(context, useStateAlias), () => "setState").when(isReactHookCallWithNameAlias("useState", context, useStateAlias), () => "useState").when(isReactHookCallWithNameAlias("useEffect", context, useEffectAlias), () => "useEffect").otherwise(() => "other");
|
|
440
|
+
}
|
|
441
|
+
function getFunctionKind(node, context, useEffectAlias) {
|
|
442
|
+
return $(node).when(isEffectFunction(context, useEffectAlias), () => "effect").when(isIIFE, () => "immediate").otherwise(() => "other");
|
|
443
|
+
}
|
|
390
444
|
var no_direct_set_state_in_use_effect_default = createRule({
|
|
391
445
|
meta: {
|
|
392
446
|
type: "problem",
|
|
@@ -402,68 +456,6 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
402
456
|
create(context) {
|
|
403
457
|
const settings = decodeSettings(context.settings);
|
|
404
458
|
const { useEffect: useEffectAlias = [], useState: useStateAlias = [] } = settings.additionalHooks ?? {};
|
|
405
|
-
function isUseEffectCallWithAlias(node) {
|
|
406
|
-
return isUseEffectCall(node, context) || useEffectAlias.some(F.flip(isReactHookCallWithNameLoose)(node));
|
|
407
|
-
}
|
|
408
|
-
function isUseStateCallWithAlias(node) {
|
|
409
|
-
return isUseStateCall(node, context) || useStateAlias.some(F.flip(isReactHookCallWithNameLoose)(node));
|
|
410
|
-
}
|
|
411
|
-
function isEffectFunction(node) {
|
|
412
|
-
return node.parent?.type === NodeType.CallExpression && node.parent.callee !== node && isUseEffectCallWithAlias(node.parent);
|
|
413
|
-
}
|
|
414
|
-
function isCleanUpFunction(_2) {
|
|
415
|
-
}
|
|
416
|
-
function isFromUseStateCall(topLevelId) {
|
|
417
|
-
const useStateCall = F.pipe(
|
|
418
|
-
findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
|
|
419
|
-
O.flatMap(getVariableNode(0)),
|
|
420
|
-
O.filter(is(NodeType.CallExpression)),
|
|
421
|
-
O.filter(isUseStateCallWithAlias)
|
|
422
|
-
);
|
|
423
|
-
if (O.isNone(useStateCall)) return false;
|
|
424
|
-
const { parent } = useStateCall.value;
|
|
425
|
-
if (!a({ id: { type: NodeType.ArrayPattern }, type: NodeType.VariableDeclarator }, parent)) return true;
|
|
426
|
-
return parent.id.elements.findIndex((e2) => e2?.type === NodeType.Identifier && e2.name === topLevelId.name) === 1;
|
|
427
|
-
}
|
|
428
|
-
function isSetStateCall(node) {
|
|
429
|
-
const topLevelId = $(node.callee).with({ type: NodeType.Identifier }, O.some).with({ type: NodeType.MemberExpression }, (n2) => {
|
|
430
|
-
if (!("name" in n2.object)) return O.none();
|
|
431
|
-
const initialScope = context.sourceCode.getScope(n2);
|
|
432
|
-
const property = getStaticValue(n2.property, initialScope);
|
|
433
|
-
if (property?.value === 1) return O.fromNullable(n2.object);
|
|
434
|
-
return O.none();
|
|
435
|
-
}).with({ type: NodeType.CallExpression }, (n2) => {
|
|
436
|
-
if (!is(NodeType.MemberExpression)(n2.callee)) return O.none();
|
|
437
|
-
if (!("name" in n2.callee.object)) return O.none();
|
|
438
|
-
const isAt = a({
|
|
439
|
-
type: NodeType.MemberExpression,
|
|
440
|
-
property: {
|
|
441
|
-
type: NodeType.Identifier,
|
|
442
|
-
name: "at"
|
|
443
|
-
}
|
|
444
|
-
}, n2.callee);
|
|
445
|
-
const [index] = n2.arguments;
|
|
446
|
-
if (!isAt || !index) return O.none();
|
|
447
|
-
const initialScope = context.sourceCode.getScope(n2);
|
|
448
|
-
const value = getStaticValue(index, initialScope);
|
|
449
|
-
if (value?.value === 1) return O.fromNullable(n2.callee.object);
|
|
450
|
-
return O.none();
|
|
451
|
-
}).otherwise(O.none);
|
|
452
|
-
return O.exists(topLevelId, isFromUseStateCall);
|
|
453
|
-
}
|
|
454
|
-
function isThenCall(node) {
|
|
455
|
-
if (node.callee.type !== NodeType.MemberExpression) return false;
|
|
456
|
-
return a({
|
|
457
|
-
type: NodeType.Identifier,
|
|
458
|
-
name: "then"
|
|
459
|
-
}, node.callee.property);
|
|
460
|
-
}
|
|
461
|
-
function getCallKind(node) {
|
|
462
|
-
return $(node).when(isThenCall, () => "then").when(isSetStateCall, () => "setState").when(isUseStateCallWithAlias, () => "useState").when(isUseEffectCallWithAlias, () => "useEffect").otherwise(() => "other");
|
|
463
|
-
}
|
|
464
|
-
function getFunctionKind(node) {
|
|
465
|
-
return $(node).when(isEffectFunction, () => "effect").when(isCleanUpFunction, () => "cleanup").when(isIIFE, () => "immediate").otherwise(() => "other");
|
|
466
|
-
}
|
|
467
459
|
const functionStack = MutList.make();
|
|
468
460
|
const effectFunctionRef = MutRef.make(null);
|
|
469
461
|
const effectFunctionIdentifiers = [];
|
|
@@ -477,7 +469,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
477
469
|
};
|
|
478
470
|
return {
|
|
479
471
|
":function"(node) {
|
|
480
|
-
const functionKind = getFunctionKind(node);
|
|
472
|
+
const functionKind = getFunctionKind(node, context, useEffectAlias);
|
|
481
473
|
MutList.append(functionStack, [node, functionKind]);
|
|
482
474
|
$(functionKind).with("effect", () => {
|
|
483
475
|
onEffectFunctionEnter(node);
|
|
@@ -491,7 +483,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
491
483
|
const effectFn = MutRef.get(effectFunctionRef);
|
|
492
484
|
const [parentFn, parentFnKind] = MutList.tail(functionStack) ?? [];
|
|
493
485
|
if (parentFn?.async) return;
|
|
494
|
-
const callKind = getCallKind(node);
|
|
486
|
+
const callKind = getCallKind(node, context, useStateAlias, useEffectAlias);
|
|
495
487
|
$(callKind).with("setState", () => {
|
|
496
488
|
if (!parentFn) return;
|
|
497
489
|
if (parentFn !== effectFn && parentFnKind !== "immediate") {
|
|
@@ -551,6 +543,15 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
551
543
|
defaultOptions: []
|
|
552
544
|
});
|
|
553
545
|
var RULE_NAME5 = "no-direct-set-state-in-use-layout-effect";
|
|
546
|
+
function isLayoutEffectFunction(context, useSomeEffectAlias) {
|
|
547
|
+
return (node) => node.parent?.type === NodeType.CallExpression && node.parent.callee !== node && isReactHookCallWithNameAlias("useLayoutEffect", context, useSomeEffectAlias)(node.parent);
|
|
548
|
+
}
|
|
549
|
+
function getCallKind2(node, context, useStateAlias, useLayoutEffectAlias) {
|
|
550
|
+
return $(node).when(isThenCall, () => "then").when(isSetStateCall(context, useStateAlias), () => "setState").when(isReactHookCallWithNameAlias("useState", context, useStateAlias), () => "useState").when(isReactHookCallWithNameAlias("useLayoutEffect", context, useLayoutEffectAlias), () => "useLayoutEffect").otherwise(() => "other");
|
|
551
|
+
}
|
|
552
|
+
function getFunctionKind2(node, context, useLayoutEffectAlias) {
|
|
553
|
+
return $(node).when(isLayoutEffectFunction(context, useLayoutEffectAlias), () => "effect").when(isIIFE, () => "immediate").otherwise(() => "other");
|
|
554
|
+
}
|
|
554
555
|
var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
555
556
|
meta: {
|
|
556
557
|
type: "problem",
|
|
@@ -566,68 +567,6 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
566
567
|
create(context) {
|
|
567
568
|
const settings = decodeSettings(context.settings);
|
|
568
569
|
const { useLayoutEffect: useLayoutEffectAlias = [], useState: useStateAlias = [] } = settings.additionalHooks ?? {};
|
|
569
|
-
function isUseLayoutEffectCallWithAlias(node) {
|
|
570
|
-
return isUseLayoutEffectCall(node, context) || useLayoutEffectAlias.some(F.flip(isReactHookCallWithNameLoose)(node));
|
|
571
|
-
}
|
|
572
|
-
function isUseStateCallWithAlias(node) {
|
|
573
|
-
return isUseStateCall(node, context) || useStateAlias.some(F.flip(isReactHookCallWithNameLoose)(node));
|
|
574
|
-
}
|
|
575
|
-
function isEffectFunction(node) {
|
|
576
|
-
return node.parent?.type === NodeType.CallExpression && node.parent.callee !== node && isUseLayoutEffectCallWithAlias(node.parent);
|
|
577
|
-
}
|
|
578
|
-
function isCleanUpFunction(_2) {
|
|
579
|
-
}
|
|
580
|
-
function isFromUseStateCall(topLevelId) {
|
|
581
|
-
const useStateCall = F.pipe(
|
|
582
|
-
findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
|
|
583
|
-
O.flatMap(getVariableNode(0)),
|
|
584
|
-
O.filter(is(NodeType.CallExpression)),
|
|
585
|
-
O.filter(isUseStateCallWithAlias)
|
|
586
|
-
);
|
|
587
|
-
if (O.isNone(useStateCall)) return false;
|
|
588
|
-
const { parent } = useStateCall.value;
|
|
589
|
-
if (!a({ id: { type: NodeType.ArrayPattern }, type: NodeType.VariableDeclarator }, parent)) return true;
|
|
590
|
-
return parent.id.elements.findIndex((e2) => e2?.type === NodeType.Identifier && e2.name === topLevelId.name) === 1;
|
|
591
|
-
}
|
|
592
|
-
function isSetStateCall(node) {
|
|
593
|
-
const topLevelId = $(node.callee).with({ type: NodeType.Identifier }, O.some).with({ type: NodeType.MemberExpression }, (n2) => {
|
|
594
|
-
if (!("name" in n2.object)) return O.none();
|
|
595
|
-
const initialScope = context.sourceCode.getScope(n2);
|
|
596
|
-
const property = getStaticValue(n2.property, initialScope);
|
|
597
|
-
if (property?.value === 1) return O.fromNullable(n2.object);
|
|
598
|
-
return O.none();
|
|
599
|
-
}).with({ type: NodeType.CallExpression }, (n2) => {
|
|
600
|
-
if (!is(NodeType.MemberExpression)(n2.callee)) return O.none();
|
|
601
|
-
if (!("name" in n2.callee.object)) return O.none();
|
|
602
|
-
const isAt = a({
|
|
603
|
-
type: NodeType.MemberExpression,
|
|
604
|
-
property: {
|
|
605
|
-
type: NodeType.Identifier,
|
|
606
|
-
name: "at"
|
|
607
|
-
}
|
|
608
|
-
}, n2.callee);
|
|
609
|
-
const [index] = n2.arguments;
|
|
610
|
-
if (!isAt || !index) return O.none();
|
|
611
|
-
const initialScope = context.sourceCode.getScope(n2);
|
|
612
|
-
const value = getStaticValue(index, initialScope);
|
|
613
|
-
if (value?.value === 1) return O.fromNullable(n2.callee.object);
|
|
614
|
-
return O.none();
|
|
615
|
-
}).otherwise(O.none);
|
|
616
|
-
return O.exists(topLevelId, isFromUseStateCall);
|
|
617
|
-
}
|
|
618
|
-
function isThenCall(node) {
|
|
619
|
-
if (node.callee.type !== NodeType.MemberExpression) return false;
|
|
620
|
-
return a({
|
|
621
|
-
type: NodeType.Identifier,
|
|
622
|
-
name: "then"
|
|
623
|
-
}, node.callee.property);
|
|
624
|
-
}
|
|
625
|
-
function getCallKind(node) {
|
|
626
|
-
return $(node).when(isThenCall, () => "then").when(isSetStateCall, () => "setState").when(isUseStateCallWithAlias, () => "useState").when(isUseLayoutEffectCallWithAlias, () => "useLayoutEffect").otherwise(() => "other");
|
|
627
|
-
}
|
|
628
|
-
function getFunctionKind(node) {
|
|
629
|
-
return $(node).when(isEffectFunction, () => "effect").when(isCleanUpFunction, () => "cleanup").when(isIIFE, () => "immediate").otherwise(() => "other");
|
|
630
|
-
}
|
|
631
570
|
const functionStack = MutList.make();
|
|
632
571
|
const effectFunctionRef = MutRef.make(null);
|
|
633
572
|
const effectFunctionIdentifiers = [];
|
|
@@ -641,7 +580,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
641
580
|
};
|
|
642
581
|
return {
|
|
643
582
|
":function"(node) {
|
|
644
|
-
const functionKind =
|
|
583
|
+
const functionKind = getFunctionKind2(node, context, useLayoutEffectAlias);
|
|
645
584
|
MutList.append(functionStack, [node, functionKind]);
|
|
646
585
|
$(functionKind).with("effect", () => {
|
|
647
586
|
onEffectFunctionEnter(node);
|
|
@@ -655,7 +594,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
655
594
|
const effectFn = MutRef.get(effectFunctionRef);
|
|
656
595
|
const [parentFn, parentFnKind] = MutList.tail(functionStack) ?? [];
|
|
657
596
|
if (parentFn?.async) return;
|
|
658
|
-
const callKind =
|
|
597
|
+
const callKind = getCallKind2(node, context, useStateAlias, useLayoutEffectAlias);
|
|
659
598
|
$(callKind).with("setState", () => {
|
|
660
599
|
if (!parentFn) return;
|
|
661
600
|
if (parentFn !== effectFn && parentFnKind !== "immediate") {
|
|
@@ -733,7 +672,7 @@ var prefer_use_state_lazy_initialization_default = createRule({
|
|
|
733
672
|
return {
|
|
734
673
|
CallExpression(node) {
|
|
735
674
|
if (!isReactHookCall(node)) return;
|
|
736
|
-
if (!isUseStateCall(node, context) && !alias.some(
|
|
675
|
+
if (!isUseStateCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) return;
|
|
737
676
|
const [useStateInput] = node.arguments;
|
|
738
677
|
if (!useStateInput) return;
|
|
739
678
|
const nestedCallExpressions = getNestedCallExpressions(useStateInput);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-hooks-extra",
|
|
3
|
-
"version": "1.6.1-next.
|
|
3
|
+
"version": "1.6.1-next.3",
|
|
4
4
|
"description": "ESLint React's ESLint plugin for React Hooks related rules.",
|
|
5
5
|
"homepage": "https://github.com/rel1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -39,13 +39,13 @@
|
|
|
39
39
|
"@typescript-eslint/type-utils": "^7.17.0",
|
|
40
40
|
"@typescript-eslint/types": "^7.17.0",
|
|
41
41
|
"@typescript-eslint/utils": "^7.17.0",
|
|
42
|
-
"@eslint-react/ast": "1.6.1-next.
|
|
43
|
-
"@eslint-react/
|
|
44
|
-
"@eslint-react/
|
|
45
|
-
"@eslint-react/
|
|
46
|
-
"@eslint-react/
|
|
47
|
-
"@eslint-react/
|
|
48
|
-
"@eslint-react/
|
|
42
|
+
"@eslint-react/ast": "1.6.1-next.3",
|
|
43
|
+
"@eslint-react/core": "1.6.1-next.3",
|
|
44
|
+
"@eslint-react/jsx": "1.6.1-next.3",
|
|
45
|
+
"@eslint-react/shared": "1.6.1-next.3",
|
|
46
|
+
"@eslint-react/types": "1.6.1-next.3",
|
|
47
|
+
"@eslint-react/tools": "1.6.1-next.3",
|
|
48
|
+
"@eslint-react/var": "1.6.1-next.3"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/react": "^18.3.3",
|