eslint-plugin-react-hooks-extra 1.6.1-beta.1 → 1.6.1-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 +112 -169
- package/dist/index.mjs +113 -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-beta.
|
|
12
|
+
var version = "1.6.1-beta.2";
|
|
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,78 @@ 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
|
+
if (node.callee.type !== ast.NodeType.MemberExpression) return false;
|
|
243
|
+
return a({
|
|
244
|
+
type: ast.NodeType.Identifier,
|
|
245
|
+
name: "then"
|
|
246
|
+
}, node.callee.property);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/rules/ensure-custom-hooks-using-other-hooks.ts
|
|
250
|
+
var RULE_NAME = "ensure-custom-hooks-using-other-hooks";
|
|
251
|
+
var ensure_custom_hooks_using_other_hooks_default = createRule({
|
|
252
|
+
meta: {
|
|
253
|
+
type: "problem",
|
|
254
|
+
docs: {
|
|
255
|
+
description: "enforce custom hooks using other hooks"
|
|
256
|
+
},
|
|
257
|
+
messages: {
|
|
258
|
+
ENSURE_CUSTOM_HOOKS_USING_OTHER_HOOKS: "A custom hook '{{name}}' should use other hooks."
|
|
259
|
+
},
|
|
260
|
+
schema: []
|
|
261
|
+
},
|
|
262
|
+
name: RULE_NAME,
|
|
263
|
+
create(context) {
|
|
264
|
+
const { ctx, listeners } = core.useHookCollector();
|
|
265
|
+
return {
|
|
266
|
+
...listeners,
|
|
267
|
+
"Program:exit"(node) {
|
|
268
|
+
const allHooks = ctx.getAllHooks(node);
|
|
269
|
+
for (const { name: name2, hookCalls, node: node2 } of allHooks.values()) {
|
|
270
|
+
if (hookCalls.length > 0) continue;
|
|
271
|
+
context.report({
|
|
272
|
+
data: {
|
|
273
|
+
name: name2.value
|
|
274
|
+
},
|
|
275
|
+
messageId: "ENSURE_CUSTOM_HOOKS_USING_OTHER_HOOKS",
|
|
276
|
+
node: node2
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
},
|
|
282
|
+
defaultOptions: []
|
|
283
|
+
});
|
|
235
284
|
var RULE_NAME2 = "ensure-use-callback-has-non-empty-deps";
|
|
236
285
|
var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
237
286
|
meta: {
|
|
@@ -251,7 +300,7 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
251
300
|
CallExpression(node) {
|
|
252
301
|
if (!core.isReactHookCall(node)) return;
|
|
253
302
|
const initialScope = context.sourceCode.getScope(node);
|
|
254
|
-
if (!core.isUseCallbackCall(node, context) && !alias.some(
|
|
303
|
+
if (!core.isUseCallbackCall(node, context) && !alias.some(core.isReactHookCallWithNameLoose(node))) {
|
|
255
304
|
return;
|
|
256
305
|
}
|
|
257
306
|
const scope = context.sourceCode.getScope(node);
|
|
@@ -329,7 +378,7 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
329
378
|
CallExpression(node) {
|
|
330
379
|
if (!core.isReactHookCall(node)) return;
|
|
331
380
|
const initialScope = context.sourceCode.getScope(node);
|
|
332
|
-
if (!core.isUseMemoCall(node, context) && !alias.some(
|
|
381
|
+
if (!core.isUseMemoCall(node, context) && !alias.some(core.isReactHookCallWithNameLoose(node))) {
|
|
333
382
|
return;
|
|
334
383
|
}
|
|
335
384
|
const scope = context.sourceCode.getScope(node);
|
|
@@ -389,6 +438,15 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
389
438
|
defaultOptions: []
|
|
390
439
|
});
|
|
391
440
|
var RULE_NAME4 = "no-direct-set-state-in-use-effect";
|
|
441
|
+
function isEffectFunction(context, useSomeEffectAlias) {
|
|
442
|
+
return (node) => node.parent?.type === ast.NodeType.CallExpression && node.parent.callee !== node && core.isReactHookCallWithNameAlias("useEffect", context, useSomeEffectAlias)(node.parent);
|
|
443
|
+
}
|
|
444
|
+
function getCallKind(node, context, useStateAlias, useEffectAlias) {
|
|
445
|
+
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");
|
|
446
|
+
}
|
|
447
|
+
function getFunctionKind(node, context, useEffectAlias) {
|
|
448
|
+
return $(node).when(isEffectFunction(context, useEffectAlias), () => "effect").when(ast.isIIFE, () => "immediate").otherwise(() => "other");
|
|
449
|
+
}
|
|
392
450
|
var no_direct_set_state_in_use_effect_default = createRule({
|
|
393
451
|
meta: {
|
|
394
452
|
type: "problem",
|
|
@@ -404,68 +462,6 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
404
462
|
create(context) {
|
|
405
463
|
const settings = shared.decodeSettings(context.settings);
|
|
406
464
|
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
465
|
const functionStack = tools.MutList.make();
|
|
470
466
|
const effectFunctionRef = tools.MutRef.make(null);
|
|
471
467
|
const effectFunctionIdentifiers = [];
|
|
@@ -479,7 +475,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
479
475
|
};
|
|
480
476
|
return {
|
|
481
477
|
":function"(node) {
|
|
482
|
-
const functionKind = getFunctionKind(node);
|
|
478
|
+
const functionKind = getFunctionKind(node, context, useEffectAlias);
|
|
483
479
|
tools.MutList.append(functionStack, [node, functionKind]);
|
|
484
480
|
$(functionKind).with("effect", () => {
|
|
485
481
|
onEffectFunctionEnter(node);
|
|
@@ -493,7 +489,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
493
489
|
const effectFn = tools.MutRef.get(effectFunctionRef);
|
|
494
490
|
const [parentFn, parentFnKind] = tools.MutList.tail(functionStack) ?? [];
|
|
495
491
|
if (parentFn?.async) return;
|
|
496
|
-
const callKind = getCallKind(node);
|
|
492
|
+
const callKind = getCallKind(node, context, useStateAlias, useEffectAlias);
|
|
497
493
|
$(callKind).with("setState", () => {
|
|
498
494
|
if (!parentFn) return;
|
|
499
495
|
if (parentFn !== effectFn && parentFnKind !== "immediate") {
|
|
@@ -553,6 +549,15 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
553
549
|
defaultOptions: []
|
|
554
550
|
});
|
|
555
551
|
var RULE_NAME5 = "no-direct-set-state-in-use-layout-effect";
|
|
552
|
+
function isLayoutEffectFunction(context, useSomeEffectAlias) {
|
|
553
|
+
return (node) => node.parent?.type === ast.NodeType.CallExpression && node.parent.callee !== node && core.isReactHookCallWithNameAlias("useLayoutEffect", context, useSomeEffectAlias)(node.parent);
|
|
554
|
+
}
|
|
555
|
+
function getCallKind2(node, context, useStateAlias, useLayoutEffectAlias) {
|
|
556
|
+
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");
|
|
557
|
+
}
|
|
558
|
+
function getFunctionKind2(node, context, useLayoutEffectAlias) {
|
|
559
|
+
return $(node).when(isLayoutEffectFunction(context, useLayoutEffectAlias), () => "effect").when(ast.isIIFE, () => "immediate").otherwise(() => "other");
|
|
560
|
+
}
|
|
556
561
|
var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
557
562
|
meta: {
|
|
558
563
|
type: "problem",
|
|
@@ -568,68 +573,6 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
568
573
|
create(context) {
|
|
569
574
|
const settings = shared.decodeSettings(context.settings);
|
|
570
575
|
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
576
|
const functionStack = tools.MutList.make();
|
|
634
577
|
const effectFunctionRef = tools.MutRef.make(null);
|
|
635
578
|
const effectFunctionIdentifiers = [];
|
|
@@ -643,7 +586,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
643
586
|
};
|
|
644
587
|
return {
|
|
645
588
|
":function"(node) {
|
|
646
|
-
const functionKind =
|
|
589
|
+
const functionKind = getFunctionKind2(node, context, useLayoutEffectAlias);
|
|
647
590
|
tools.MutList.append(functionStack, [node, functionKind]);
|
|
648
591
|
$(functionKind).with("effect", () => {
|
|
649
592
|
onEffectFunctionEnter(node);
|
|
@@ -657,7 +600,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
657
600
|
const effectFn = tools.MutRef.get(effectFunctionRef);
|
|
658
601
|
const [parentFn, parentFnKind] = tools.MutList.tail(functionStack) ?? [];
|
|
659
602
|
if (parentFn?.async) return;
|
|
660
|
-
const callKind =
|
|
603
|
+
const callKind = getCallKind2(node, context, useStateAlias, useLayoutEffectAlias);
|
|
661
604
|
$(callKind).with("setState", () => {
|
|
662
605
|
if (!parentFn) return;
|
|
663
606
|
if (parentFn !== effectFn && parentFnKind !== "immediate") {
|
|
@@ -735,7 +678,7 @@ var prefer_use_state_lazy_initialization_default = createRule({
|
|
|
735
678
|
return {
|
|
736
679
|
CallExpression(node) {
|
|
737
680
|
if (!core.isReactHookCall(node)) return;
|
|
738
|
-
if (!core.isUseStateCall(node, context) && !alias.some(
|
|
681
|
+
if (!core.isUseStateCall(node, context) && !alias.some(core.isReactHookCallWithNameLoose(node))) return;
|
|
739
682
|
const [useStateInput] = node.arguments;
|
|
740
683
|
if (!useStateInput) return;
|
|
741
684
|
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-beta.
|
|
10
|
+
var version = "1.6.1-beta.2";
|
|
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,78 @@ 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
|
+
if (node.callee.type !== NodeType.MemberExpression) return false;
|
|
241
|
+
return a({
|
|
242
|
+
type: NodeType.Identifier,
|
|
243
|
+
name: "then"
|
|
244
|
+
}, node.callee.property);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// src/rules/ensure-custom-hooks-using-other-hooks.ts
|
|
248
|
+
var RULE_NAME = "ensure-custom-hooks-using-other-hooks";
|
|
249
|
+
var ensure_custom_hooks_using_other_hooks_default = createRule({
|
|
250
|
+
meta: {
|
|
251
|
+
type: "problem",
|
|
252
|
+
docs: {
|
|
253
|
+
description: "enforce custom hooks using other hooks"
|
|
254
|
+
},
|
|
255
|
+
messages: {
|
|
256
|
+
ENSURE_CUSTOM_HOOKS_USING_OTHER_HOOKS: "A custom hook '{{name}}' should use other hooks."
|
|
257
|
+
},
|
|
258
|
+
schema: []
|
|
259
|
+
},
|
|
260
|
+
name: RULE_NAME,
|
|
261
|
+
create(context) {
|
|
262
|
+
const { ctx, listeners } = useHookCollector();
|
|
263
|
+
return {
|
|
264
|
+
...listeners,
|
|
265
|
+
"Program:exit"(node) {
|
|
266
|
+
const allHooks = ctx.getAllHooks(node);
|
|
267
|
+
for (const { name: name2, hookCalls, node: node2 } of allHooks.values()) {
|
|
268
|
+
if (hookCalls.length > 0) continue;
|
|
269
|
+
context.report({
|
|
270
|
+
data: {
|
|
271
|
+
name: name2.value
|
|
272
|
+
},
|
|
273
|
+
messageId: "ENSURE_CUSTOM_HOOKS_USING_OTHER_HOOKS",
|
|
274
|
+
node: node2
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
},
|
|
280
|
+
defaultOptions: []
|
|
281
|
+
});
|
|
233
282
|
var RULE_NAME2 = "ensure-use-callback-has-non-empty-deps";
|
|
234
283
|
var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
235
284
|
meta: {
|
|
@@ -249,7 +298,7 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
249
298
|
CallExpression(node) {
|
|
250
299
|
if (!isReactHookCall(node)) return;
|
|
251
300
|
const initialScope = context.sourceCode.getScope(node);
|
|
252
|
-
if (!isUseCallbackCall(node, context) && !alias.some(
|
|
301
|
+
if (!isUseCallbackCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) {
|
|
253
302
|
return;
|
|
254
303
|
}
|
|
255
304
|
const scope = context.sourceCode.getScope(node);
|
|
@@ -327,7 +376,7 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
327
376
|
CallExpression(node) {
|
|
328
377
|
if (!isReactHookCall(node)) return;
|
|
329
378
|
const initialScope = context.sourceCode.getScope(node);
|
|
330
|
-
if (!isUseMemoCall(node, context) && !alias.some(
|
|
379
|
+
if (!isUseMemoCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) {
|
|
331
380
|
return;
|
|
332
381
|
}
|
|
333
382
|
const scope = context.sourceCode.getScope(node);
|
|
@@ -387,6 +436,15 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
387
436
|
defaultOptions: []
|
|
388
437
|
});
|
|
389
438
|
var RULE_NAME4 = "no-direct-set-state-in-use-effect";
|
|
439
|
+
function isEffectFunction(context, useSomeEffectAlias) {
|
|
440
|
+
return (node) => node.parent?.type === NodeType.CallExpression && node.parent.callee !== node && isReactHookCallWithNameAlias("useEffect", context, useSomeEffectAlias)(node.parent);
|
|
441
|
+
}
|
|
442
|
+
function getCallKind(node, context, useStateAlias, useEffectAlias) {
|
|
443
|
+
return $(node).when(isThenCall, () => "then").when(isSetStateCall(context, useStateAlias), () => "setState").when(isReactHookCallWithNameAlias("useState", context, useStateAlias), () => "useState").when(isReactHookCallWithNameAlias("useEffect", context, useEffectAlias), () => "useEffect").otherwise(() => "other");
|
|
444
|
+
}
|
|
445
|
+
function getFunctionKind(node, context, useEffectAlias) {
|
|
446
|
+
return $(node).when(isEffectFunction(context, useEffectAlias), () => "effect").when(isIIFE, () => "immediate").otherwise(() => "other");
|
|
447
|
+
}
|
|
390
448
|
var no_direct_set_state_in_use_effect_default = createRule({
|
|
391
449
|
meta: {
|
|
392
450
|
type: "problem",
|
|
@@ -402,68 +460,6 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
402
460
|
create(context) {
|
|
403
461
|
const settings = decodeSettings(context.settings);
|
|
404
462
|
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
463
|
const functionStack = MutList.make();
|
|
468
464
|
const effectFunctionRef = MutRef.make(null);
|
|
469
465
|
const effectFunctionIdentifiers = [];
|
|
@@ -477,7 +473,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
477
473
|
};
|
|
478
474
|
return {
|
|
479
475
|
":function"(node) {
|
|
480
|
-
const functionKind = getFunctionKind(node);
|
|
476
|
+
const functionKind = getFunctionKind(node, context, useEffectAlias);
|
|
481
477
|
MutList.append(functionStack, [node, functionKind]);
|
|
482
478
|
$(functionKind).with("effect", () => {
|
|
483
479
|
onEffectFunctionEnter(node);
|
|
@@ -491,7 +487,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
491
487
|
const effectFn = MutRef.get(effectFunctionRef);
|
|
492
488
|
const [parentFn, parentFnKind] = MutList.tail(functionStack) ?? [];
|
|
493
489
|
if (parentFn?.async) return;
|
|
494
|
-
const callKind = getCallKind(node);
|
|
490
|
+
const callKind = getCallKind(node, context, useStateAlias, useEffectAlias);
|
|
495
491
|
$(callKind).with("setState", () => {
|
|
496
492
|
if (!parentFn) return;
|
|
497
493
|
if (parentFn !== effectFn && parentFnKind !== "immediate") {
|
|
@@ -551,6 +547,15 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
551
547
|
defaultOptions: []
|
|
552
548
|
});
|
|
553
549
|
var RULE_NAME5 = "no-direct-set-state-in-use-layout-effect";
|
|
550
|
+
function isLayoutEffectFunction(context, useSomeEffectAlias) {
|
|
551
|
+
return (node) => node.parent?.type === NodeType.CallExpression && node.parent.callee !== node && isReactHookCallWithNameAlias("useLayoutEffect", context, useSomeEffectAlias)(node.parent);
|
|
552
|
+
}
|
|
553
|
+
function getCallKind2(node, context, useStateAlias, useLayoutEffectAlias) {
|
|
554
|
+
return $(node).when(isThenCall, () => "then").when(isSetStateCall(context, useStateAlias), () => "setState").when(isReactHookCallWithNameAlias("useState", context, useStateAlias), () => "useState").when(isReactHookCallWithNameAlias("useLayoutEffect", context, useLayoutEffectAlias), () => "useLayoutEffect").otherwise(() => "other");
|
|
555
|
+
}
|
|
556
|
+
function getFunctionKind2(node, context, useLayoutEffectAlias) {
|
|
557
|
+
return $(node).when(isLayoutEffectFunction(context, useLayoutEffectAlias), () => "effect").when(isIIFE, () => "immediate").otherwise(() => "other");
|
|
558
|
+
}
|
|
554
559
|
var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
555
560
|
meta: {
|
|
556
561
|
type: "problem",
|
|
@@ -566,68 +571,6 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
566
571
|
create(context) {
|
|
567
572
|
const settings = decodeSettings(context.settings);
|
|
568
573
|
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
574
|
const functionStack = MutList.make();
|
|
632
575
|
const effectFunctionRef = MutRef.make(null);
|
|
633
576
|
const effectFunctionIdentifiers = [];
|
|
@@ -641,7 +584,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
641
584
|
};
|
|
642
585
|
return {
|
|
643
586
|
":function"(node) {
|
|
644
|
-
const functionKind =
|
|
587
|
+
const functionKind = getFunctionKind2(node, context, useLayoutEffectAlias);
|
|
645
588
|
MutList.append(functionStack, [node, functionKind]);
|
|
646
589
|
$(functionKind).with("effect", () => {
|
|
647
590
|
onEffectFunctionEnter(node);
|
|
@@ -655,7 +598,7 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
655
598
|
const effectFn = MutRef.get(effectFunctionRef);
|
|
656
599
|
const [parentFn, parentFnKind] = MutList.tail(functionStack) ?? [];
|
|
657
600
|
if (parentFn?.async) return;
|
|
658
|
-
const callKind =
|
|
601
|
+
const callKind = getCallKind2(node, context, useStateAlias, useLayoutEffectAlias);
|
|
659
602
|
$(callKind).with("setState", () => {
|
|
660
603
|
if (!parentFn) return;
|
|
661
604
|
if (parentFn !== effectFn && parentFnKind !== "immediate") {
|
|
@@ -733,7 +676,7 @@ var prefer_use_state_lazy_initialization_default = createRule({
|
|
|
733
676
|
return {
|
|
734
677
|
CallExpression(node) {
|
|
735
678
|
if (!isReactHookCall(node)) return;
|
|
736
|
-
if (!isUseStateCall(node, context) && !alias.some(
|
|
679
|
+
if (!isUseStateCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) return;
|
|
737
680
|
const [useStateInput] = node.arguments;
|
|
738
681
|
if (!useStateInput) return;
|
|
739
682
|
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-beta.
|
|
3
|
+
"version": "1.6.1-beta.2",
|
|
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-beta.
|
|
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-beta.2",
|
|
43
|
+
"@eslint-react/core": "1.6.1-beta.2",
|
|
44
|
+
"@eslint-react/jsx": "1.6.1-beta.2",
|
|
45
|
+
"@eslint-react/tools": "1.6.1-beta.2",
|
|
46
|
+
"@eslint-react/shared": "1.6.1-beta.2",
|
|
47
|
+
"@eslint-react/types": "1.6.1-beta.2",
|
|
48
|
+
"@eslint-react/var": "1.6.1-beta.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/react": "^18.3.3",
|