eslint-plugin-react-hooks-extra 1.9.1 → 1.9.2-next.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/LICENSE +1 -1
- package/dist/index.js +48 -47
- package/dist/index.mjs +49 -48
- package/package.json +8 -8
package/LICENSE
CHANGED
package/dist/index.js
CHANGED
|
@@ -5,18 +5,19 @@ var shared = require('@eslint-react/shared');
|
|
|
5
5
|
var ast = require('@eslint-react/ast');
|
|
6
6
|
var tools = require('@eslint-react/tools');
|
|
7
7
|
var _var = require('@eslint-react/var');
|
|
8
|
+
var types = require('@typescript-eslint/types');
|
|
8
9
|
var astUtils = require('@typescript-eslint/utils/ast-utils');
|
|
9
10
|
|
|
10
11
|
// package.json
|
|
11
12
|
var name = "eslint-plugin-react-hooks-extra";
|
|
12
|
-
var version = "1.9.
|
|
13
|
+
var version = "1.9.2-next.2";
|
|
13
14
|
var createRule = shared.createRuleForPlugin("hooks-extra");
|
|
14
15
|
function isFromHookCall(name2, context, settings, predicate = tools.F.constTrue) {
|
|
15
16
|
const hookAlias = settings.additionalHooks?.[name2] ?? [];
|
|
16
17
|
return (topLevelId) => tools.F.pipe(
|
|
17
18
|
_var.findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
|
|
18
19
|
tools.O.flatMap(_var.getVariableNode(0)),
|
|
19
|
-
tools.O.filter(ast.is(
|
|
20
|
+
tools.O.filter(ast.is(types.AST_NODE_TYPES.CallExpression)),
|
|
20
21
|
tools.O.filter(core.isReactHookCallWithNameAlias(name2, context, hookAlias)),
|
|
21
22
|
tools.O.exists((call) => predicate(topLevelId, call))
|
|
22
23
|
);
|
|
@@ -24,8 +25,8 @@ function isFromHookCall(name2, context, settings, predicate = tools.F.constTrue)
|
|
|
24
25
|
function isFromUseStateCall(context, settings) {
|
|
25
26
|
const predicate = (topLevelId, call) => {
|
|
26
27
|
const { parent } = call;
|
|
27
|
-
if (!("id" in parent && parent.id?.type ===
|
|
28
|
-
return parent.id.elements.findIndex((e2) => e2?.type ===
|
|
28
|
+
if (!("id" in parent && parent.id?.type === types.AST_NODE_TYPES.ArrayPattern)) return true;
|
|
29
|
+
return parent.id.elements.findIndex((e2) => e2?.type === types.AST_NODE_TYPES.Identifier && e2.name === topLevelId.name) === 1;
|
|
29
30
|
};
|
|
30
31
|
return isFromHookCall("useState", context, settings, predicate);
|
|
31
32
|
}
|
|
@@ -218,24 +219,24 @@ function isSetFunctionCall(context, settings) {
|
|
|
218
219
|
const isIdFromUseStateCall = isFromUseStateCall(context, settings);
|
|
219
220
|
return (node) => {
|
|
220
221
|
switch (node.callee.type) {
|
|
221
|
-
case
|
|
222
|
+
case types.AST_NODE_TYPES.Identifier: {
|
|
222
223
|
return isIdFromUseStateCall(node.callee);
|
|
223
224
|
}
|
|
224
|
-
case
|
|
225
|
+
case types.AST_NODE_TYPES.MemberExpression: {
|
|
225
226
|
if (!("name" in node.callee.object)) return false;
|
|
226
227
|
const initialScope = context.sourceCode.getScope(node);
|
|
227
228
|
const property = astUtils.getStaticValue(node.callee.property, initialScope);
|
|
228
229
|
if (property?.value === 1) return isIdFromUseStateCall(node.callee.object);
|
|
229
230
|
return false;
|
|
230
231
|
}
|
|
231
|
-
case
|
|
232
|
+
case types.AST_NODE_TYPES.CallExpression: {
|
|
232
233
|
const callee = node.callee.callee;
|
|
233
|
-
if (callee.type !==
|
|
234
|
+
if (callee.type !== types.AST_NODE_TYPES.MemberExpression) return false;
|
|
234
235
|
if (!("name" in callee.object)) return false;
|
|
235
236
|
const isAt = a({
|
|
236
|
-
type:
|
|
237
|
+
type: types.AST_NODE_TYPES.MemberExpression,
|
|
237
238
|
property: {
|
|
238
|
-
type:
|
|
239
|
+
type: types.AST_NODE_TYPES.Identifier,
|
|
239
240
|
name: "at"
|
|
240
241
|
}
|
|
241
242
|
}, callee);
|
|
@@ -253,17 +254,17 @@ function isSetFunctionCall(context, settings) {
|
|
|
253
254
|
};
|
|
254
255
|
}
|
|
255
256
|
function isThenCall(node) {
|
|
256
|
-
return node.callee.type ===
|
|
257
|
+
return node.callee.type === types.AST_NODE_TYPES.MemberExpression && node.callee.property.type === types.AST_NODE_TYPES.Identifier && node.callee.property.name === "then";
|
|
257
258
|
}
|
|
258
259
|
function isVariableDeclaratorFromHookCall(node) {
|
|
259
|
-
if (node.type !==
|
|
260
|
-
if (node.id.type !==
|
|
261
|
-
if (node.init?.type !==
|
|
260
|
+
if (node.type !== types.AST_NODE_TYPES.VariableDeclarator) return false;
|
|
261
|
+
if (node.id.type !== types.AST_NODE_TYPES.Identifier) return false;
|
|
262
|
+
if (node.init?.type !== types.AST_NODE_TYPES.CallExpression) return false;
|
|
262
263
|
switch (node.init.callee.type) {
|
|
263
|
-
case
|
|
264
|
+
case types.AST_NODE_TYPES.Identifier:
|
|
264
265
|
return core.isReactHookName(node.init.callee.name);
|
|
265
|
-
case
|
|
266
|
-
return node.init.callee.property.type ===
|
|
266
|
+
case types.AST_NODE_TYPES.MemberExpression:
|
|
267
|
+
return node.init.callee.property.type === types.AST_NODE_TYPES.Identifier && core.isReactHookName(node.init.callee.property.name);
|
|
267
268
|
default:
|
|
268
269
|
return false;
|
|
269
270
|
}
|
|
@@ -338,11 +339,11 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
338
339
|
return;
|
|
339
340
|
}
|
|
340
341
|
const hasEmptyDeps = tools.F.pipe(
|
|
341
|
-
$(deps).with({ type:
|
|
342
|
+
$(deps).with({ type: types.AST_NODE_TYPES.ArrayExpression }, tools.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n2) => {
|
|
342
343
|
return tools.F.pipe(
|
|
343
344
|
_var.findVariable(n2.name, initialScope),
|
|
344
345
|
tools.O.flatMap(_var.getVariableNode(0)),
|
|
345
|
-
tools.O.filter(ast.is(
|
|
346
|
+
tools.O.filter(ast.is(types.AST_NODE_TYPES.ArrayExpression))
|
|
346
347
|
);
|
|
347
348
|
}).otherwise(tools.O.none),
|
|
348
349
|
tools.O.exists((x2) => x2.elements.length === 0)
|
|
@@ -356,12 +357,12 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
356
357
|
return;
|
|
357
358
|
}
|
|
358
359
|
const isReferencedToComponentScope = tools.F.pipe(
|
|
359
|
-
$(cb).with({ type:
|
|
360
|
-
if (n2.body.type ===
|
|
360
|
+
$(cb).with({ type: types.AST_NODE_TYPES.ArrowFunctionExpression }, (n2) => {
|
|
361
|
+
if (n2.body.type === types.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
361
362
|
return tools.O.some(n2.body);
|
|
362
363
|
}
|
|
363
364
|
return tools.O.some(n2);
|
|
364
|
-
}).with({ type:
|
|
365
|
+
}).with({ type: types.AST_NODE_TYPES.FunctionExpression }, tools.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n2) => {
|
|
365
366
|
return tools.F.pipe(
|
|
366
367
|
_var.findVariable(n2.name, initialScope),
|
|
367
368
|
tools.O.flatMap(_var.getVariableNode(0)),
|
|
@@ -416,11 +417,11 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
416
417
|
return;
|
|
417
418
|
}
|
|
418
419
|
const hasEmptyDeps = tools.F.pipe(
|
|
419
|
-
$(deps).with({ type:
|
|
420
|
+
$(deps).with({ type: types.AST_NODE_TYPES.ArrayExpression }, tools.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n2) => {
|
|
420
421
|
return tools.F.pipe(
|
|
421
422
|
_var.findVariable(n2.name, initialScope),
|
|
422
423
|
tools.O.flatMap(_var.getVariableNode(0)),
|
|
423
|
-
tools.O.filter(ast.is(
|
|
424
|
+
tools.O.filter(ast.is(types.AST_NODE_TYPES.ArrayExpression))
|
|
424
425
|
);
|
|
425
426
|
}).otherwise(tools.O.none),
|
|
426
427
|
tools.O.exists((x2) => x2.elements.length === 0)
|
|
@@ -434,12 +435,12 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
434
435
|
return;
|
|
435
436
|
}
|
|
436
437
|
const isReferencedToComponentScope = tools.F.pipe(
|
|
437
|
-
$(cb).with({ type:
|
|
438
|
-
if (n2.body.type ===
|
|
438
|
+
$(cb).with({ type: types.AST_NODE_TYPES.ArrowFunctionExpression }, (n2) => {
|
|
439
|
+
if (n2.body.type === types.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
439
440
|
return tools.O.some(n2.body);
|
|
440
441
|
}
|
|
441
442
|
return tools.O.some(n2);
|
|
442
|
-
}).with({ type:
|
|
443
|
+
}).with({ type: types.AST_NODE_TYPES.FunctionExpression }, tools.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n2) => {
|
|
443
444
|
return tools.F.pipe(
|
|
444
445
|
_var.findVariable(n2.name, initialScope),
|
|
445
446
|
tools.O.flatMap(_var.getVariableNode(0)),
|
|
@@ -497,13 +498,13 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
497
498
|
tools.MutRef.update(effectFunctionRef, (current) => current === node ? null : current);
|
|
498
499
|
};
|
|
499
500
|
function isEffectFunction(node) {
|
|
500
|
-
return node.parent?.type ===
|
|
501
|
+
return node.parent?.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee !== node && isUseEffectCall(node.parent);
|
|
501
502
|
}
|
|
502
503
|
function getCallKind(node) {
|
|
503
504
|
return $(node).when(isUseStateCall2, () => "useState").when(isUseEffectCall, () => "useEffect").when(isSetStateCall, () => "setState").when(isThenCall, () => "then").otherwise(() => "other");
|
|
504
505
|
}
|
|
505
506
|
function getFunctionKind(node) {
|
|
506
|
-
return $(node).when(isEffectFunction, () => "effect").when(ast.
|
|
507
|
+
return $(node).when(isEffectFunction, () => "effect").when(ast.isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
|
|
507
508
|
}
|
|
508
509
|
return {
|
|
509
510
|
":function"(node) {
|
|
@@ -550,10 +551,10 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
550
551
|
}).otherwise(tools.F.constVoid);
|
|
551
552
|
},
|
|
552
553
|
Identifier(node) {
|
|
553
|
-
if (node.parent.type ===
|
|
554
|
+
if (node.parent.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee === node) return;
|
|
554
555
|
if (!isIdFromUseStateCall(node)) return;
|
|
555
556
|
switch (node.parent.type) {
|
|
556
|
-
case
|
|
557
|
+
case types.AST_NODE_TYPES.CallExpression: {
|
|
557
558
|
const [firstArg] = node.parent.arguments;
|
|
558
559
|
if (node !== firstArg) break;
|
|
559
560
|
if (isUseCallbackCall2(node.parent)) {
|
|
@@ -569,9 +570,9 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
569
570
|
}
|
|
570
571
|
break;
|
|
571
572
|
}
|
|
572
|
-
case
|
|
573
|
+
case types.AST_NODE_TYPES.ArrowFunctionExpression: {
|
|
573
574
|
const parent = node.parent.parent;
|
|
574
|
-
if (parent.type !==
|
|
575
|
+
if (parent.type !== types.AST_NODE_TYPES.CallExpression) break;
|
|
575
576
|
if (!isUseMemoCall2(parent)) break;
|
|
576
577
|
const maybeVd = ast.traverseUpGuard(parent, isVariableDeclaratorFromHookCall);
|
|
577
578
|
if (tools.O.isNone(maybeVd)) break;
|
|
@@ -585,11 +586,11 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
585
586
|
const getSetStateCalls = (id, initialScope) => {
|
|
586
587
|
const node = tools.O.flatMap(_var.findVariable(id, initialScope), _var.getVariableNode(0)).pipe(tools.O.getOrNull);
|
|
587
588
|
switch (node?.type) {
|
|
588
|
-
case
|
|
589
|
-
case
|
|
590
|
-
case
|
|
589
|
+
case types.AST_NODE_TYPES.FunctionDeclaration:
|
|
590
|
+
case types.AST_NODE_TYPES.FunctionExpression:
|
|
591
|
+
case types.AST_NODE_TYPES.ArrowFunctionExpression:
|
|
591
592
|
return indirectSetStateCalls.get(node) ?? [];
|
|
592
|
-
case
|
|
593
|
+
case types.AST_NODE_TYPES.CallExpression:
|
|
593
594
|
return indirectSetStateCallsInHooks.get(node) ?? indirectSetStateCallsAsArgs.get(node) ?? [];
|
|
594
595
|
}
|
|
595
596
|
return [];
|
|
@@ -671,13 +672,13 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
671
672
|
tools.MutRef.update(effectFunctionRef, (current) => current === node ? null : current);
|
|
672
673
|
};
|
|
673
674
|
function isEffectFunction(node) {
|
|
674
|
-
return node.parent?.type ===
|
|
675
|
+
return node.parent?.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee !== node && isUseEffectCall(node.parent);
|
|
675
676
|
}
|
|
676
677
|
function getCallKind(node) {
|
|
677
678
|
return $(node).when(isUseStateCall2, () => "useState").when(isUseEffectCall, () => "useLayoutEffect").when(isSetStateCall, () => "setState").when(isThenCall, () => "then").otherwise(() => "other");
|
|
678
679
|
}
|
|
679
680
|
function getFunctionKind(node) {
|
|
680
|
-
return $(node).when(isEffectFunction, () => "effect").when(ast.
|
|
681
|
+
return $(node).when(isEffectFunction, () => "effect").when(ast.isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
|
|
681
682
|
}
|
|
682
683
|
return {
|
|
683
684
|
":function"(node) {
|
|
@@ -724,10 +725,10 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
724
725
|
}).otherwise(tools.F.constVoid);
|
|
725
726
|
},
|
|
726
727
|
Identifier(node) {
|
|
727
|
-
if (node.parent.type ===
|
|
728
|
+
if (node.parent.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee === node) return;
|
|
728
729
|
if (!isIdFromUseStateCall(node)) return;
|
|
729
730
|
switch (node.parent.type) {
|
|
730
|
-
case
|
|
731
|
+
case types.AST_NODE_TYPES.CallExpression: {
|
|
731
732
|
const [firstArg] = node.parent.arguments;
|
|
732
733
|
if (node !== firstArg) break;
|
|
733
734
|
if (isUseCallbackCall2(node.parent)) {
|
|
@@ -743,9 +744,9 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
743
744
|
}
|
|
744
745
|
break;
|
|
745
746
|
}
|
|
746
|
-
case
|
|
747
|
+
case types.AST_NODE_TYPES.ArrowFunctionExpression: {
|
|
747
748
|
const parent = node.parent.parent;
|
|
748
|
-
if (parent.type !==
|
|
749
|
+
if (parent.type !== types.AST_NODE_TYPES.CallExpression) break;
|
|
749
750
|
if (!isUseMemoCall2(parent)) break;
|
|
750
751
|
const maybeVd = ast.traverseUpGuard(parent, isVariableDeclaratorFromHookCall);
|
|
751
752
|
if (tools.O.isNone(maybeVd)) break;
|
|
@@ -759,11 +760,11 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
759
760
|
const getSetStateCalls = (id, initialScope) => {
|
|
760
761
|
const node = tools.O.flatMap(_var.findVariable(id, initialScope), _var.getVariableNode(0)).pipe(tools.O.getOrNull);
|
|
761
762
|
switch (node?.type) {
|
|
762
|
-
case
|
|
763
|
-
case
|
|
764
|
-
case
|
|
763
|
+
case types.AST_NODE_TYPES.FunctionDeclaration:
|
|
764
|
+
case types.AST_NODE_TYPES.FunctionExpression:
|
|
765
|
+
case types.AST_NODE_TYPES.ArrowFunctionExpression:
|
|
765
766
|
return indirectSetStateCalls.get(node) ?? [];
|
|
766
|
-
case
|
|
767
|
+
case types.AST_NODE_TYPES.CallExpression:
|
|
767
768
|
return indirectSetStateCallsInHooks.get(node) ?? indirectSetStateCallsAsArgs.get(node) ?? [];
|
|
768
769
|
}
|
|
769
770
|
return [];
|
package/dist/index.mjs
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { useHookCollector, isReactHookCall, isUseCallbackCall, isReactHookCallWithNameLoose, isUseMemoCall, isReactHookCallWithNameAlias, isUseStateCall, isReactHookName } from '@eslint-react/core';
|
|
2
2
|
import { createRuleForPlugin, decodeSettings } from '@eslint-react/shared';
|
|
3
|
-
import { isFunction,
|
|
3
|
+
import { isFunction, is, traverseUpGuard, getNestedIdentifiers, getNestedCallExpressions, isFunctionOfImmediatelyInvoked } from '@eslint-react/ast';
|
|
4
4
|
import { F, O, MutRef } from '@eslint-react/tools';
|
|
5
5
|
import { findVariable, getVariableNode } from '@eslint-react/var';
|
|
6
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
6
7
|
import { getStaticValue } from '@typescript-eslint/utils/ast-utils';
|
|
7
8
|
|
|
8
9
|
// package.json
|
|
9
10
|
var name = "eslint-plugin-react-hooks-extra";
|
|
10
|
-
var version = "1.9.
|
|
11
|
+
var version = "1.9.2-next.2";
|
|
11
12
|
var createRule = createRuleForPlugin("hooks-extra");
|
|
12
13
|
function isFromHookCall(name2, context, settings, predicate = F.constTrue) {
|
|
13
14
|
const hookAlias = settings.additionalHooks?.[name2] ?? [];
|
|
14
15
|
return (topLevelId) => F.pipe(
|
|
15
16
|
findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
|
|
16
17
|
O.flatMap(getVariableNode(0)),
|
|
17
|
-
O.filter(is(
|
|
18
|
+
O.filter(is(AST_NODE_TYPES.CallExpression)),
|
|
18
19
|
O.filter(isReactHookCallWithNameAlias(name2, context, hookAlias)),
|
|
19
20
|
O.exists((call) => predicate(topLevelId, call))
|
|
20
21
|
);
|
|
@@ -22,8 +23,8 @@ function isFromHookCall(name2, context, settings, predicate = F.constTrue) {
|
|
|
22
23
|
function isFromUseStateCall(context, settings) {
|
|
23
24
|
const predicate = (topLevelId, call) => {
|
|
24
25
|
const { parent } = call;
|
|
25
|
-
if (!("id" in parent && parent.id?.type ===
|
|
26
|
-
return parent.id.elements.findIndex((e2) => e2?.type ===
|
|
26
|
+
if (!("id" in parent && parent.id?.type === AST_NODE_TYPES.ArrayPattern)) return true;
|
|
27
|
+
return parent.id.elements.findIndex((e2) => e2?.type === AST_NODE_TYPES.Identifier && e2.name === topLevelId.name) === 1;
|
|
27
28
|
};
|
|
28
29
|
return isFromHookCall("useState", context, settings, predicate);
|
|
29
30
|
}
|
|
@@ -216,24 +217,24 @@ function isSetFunctionCall(context, settings) {
|
|
|
216
217
|
const isIdFromUseStateCall = isFromUseStateCall(context, settings);
|
|
217
218
|
return (node) => {
|
|
218
219
|
switch (node.callee.type) {
|
|
219
|
-
case
|
|
220
|
+
case AST_NODE_TYPES.Identifier: {
|
|
220
221
|
return isIdFromUseStateCall(node.callee);
|
|
221
222
|
}
|
|
222
|
-
case
|
|
223
|
+
case AST_NODE_TYPES.MemberExpression: {
|
|
223
224
|
if (!("name" in node.callee.object)) return false;
|
|
224
225
|
const initialScope = context.sourceCode.getScope(node);
|
|
225
226
|
const property = getStaticValue(node.callee.property, initialScope);
|
|
226
227
|
if (property?.value === 1) return isIdFromUseStateCall(node.callee.object);
|
|
227
228
|
return false;
|
|
228
229
|
}
|
|
229
|
-
case
|
|
230
|
+
case AST_NODE_TYPES.CallExpression: {
|
|
230
231
|
const callee = node.callee.callee;
|
|
231
|
-
if (callee.type !==
|
|
232
|
+
if (callee.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
232
233
|
if (!("name" in callee.object)) return false;
|
|
233
234
|
const isAt = a({
|
|
234
|
-
type:
|
|
235
|
+
type: AST_NODE_TYPES.MemberExpression,
|
|
235
236
|
property: {
|
|
236
|
-
type:
|
|
237
|
+
type: AST_NODE_TYPES.Identifier,
|
|
237
238
|
name: "at"
|
|
238
239
|
}
|
|
239
240
|
}, callee);
|
|
@@ -251,17 +252,17 @@ function isSetFunctionCall(context, settings) {
|
|
|
251
252
|
};
|
|
252
253
|
}
|
|
253
254
|
function isThenCall(node) {
|
|
254
|
-
return node.callee.type ===
|
|
255
|
+
return node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "then";
|
|
255
256
|
}
|
|
256
257
|
function isVariableDeclaratorFromHookCall(node) {
|
|
257
|
-
if (node.type !==
|
|
258
|
-
if (node.id.type !==
|
|
259
|
-
if (node.init?.type !==
|
|
258
|
+
if (node.type !== AST_NODE_TYPES.VariableDeclarator) return false;
|
|
259
|
+
if (node.id.type !== AST_NODE_TYPES.Identifier) return false;
|
|
260
|
+
if (node.init?.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
260
261
|
switch (node.init.callee.type) {
|
|
261
|
-
case
|
|
262
|
+
case AST_NODE_TYPES.Identifier:
|
|
262
263
|
return isReactHookName(node.init.callee.name);
|
|
263
|
-
case
|
|
264
|
-
return node.init.callee.property.type ===
|
|
264
|
+
case AST_NODE_TYPES.MemberExpression:
|
|
265
|
+
return node.init.callee.property.type === AST_NODE_TYPES.Identifier && isReactHookName(node.init.callee.property.name);
|
|
265
266
|
default:
|
|
266
267
|
return false;
|
|
267
268
|
}
|
|
@@ -336,11 +337,11 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
336
337
|
return;
|
|
337
338
|
}
|
|
338
339
|
const hasEmptyDeps = F.pipe(
|
|
339
|
-
$(deps).with({ type:
|
|
340
|
+
$(deps).with({ type: AST_NODE_TYPES.ArrayExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n2) => {
|
|
340
341
|
return F.pipe(
|
|
341
342
|
findVariable(n2.name, initialScope),
|
|
342
343
|
O.flatMap(getVariableNode(0)),
|
|
343
|
-
O.filter(is(
|
|
344
|
+
O.filter(is(AST_NODE_TYPES.ArrayExpression))
|
|
344
345
|
);
|
|
345
346
|
}).otherwise(O.none),
|
|
346
347
|
O.exists((x2) => x2.elements.length === 0)
|
|
@@ -354,12 +355,12 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
354
355
|
return;
|
|
355
356
|
}
|
|
356
357
|
const isReferencedToComponentScope = F.pipe(
|
|
357
|
-
$(cb).with({ type:
|
|
358
|
-
if (n2.body.type ===
|
|
358
|
+
$(cb).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n2) => {
|
|
359
|
+
if (n2.body.type === AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
359
360
|
return O.some(n2.body);
|
|
360
361
|
}
|
|
361
362
|
return O.some(n2);
|
|
362
|
-
}).with({ type:
|
|
363
|
+
}).with({ type: AST_NODE_TYPES.FunctionExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n2) => {
|
|
363
364
|
return F.pipe(
|
|
364
365
|
findVariable(n2.name, initialScope),
|
|
365
366
|
O.flatMap(getVariableNode(0)),
|
|
@@ -414,11 +415,11 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
414
415
|
return;
|
|
415
416
|
}
|
|
416
417
|
const hasEmptyDeps = F.pipe(
|
|
417
|
-
$(deps).with({ type:
|
|
418
|
+
$(deps).with({ type: AST_NODE_TYPES.ArrayExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n2) => {
|
|
418
419
|
return F.pipe(
|
|
419
420
|
findVariable(n2.name, initialScope),
|
|
420
421
|
O.flatMap(getVariableNode(0)),
|
|
421
|
-
O.filter(is(
|
|
422
|
+
O.filter(is(AST_NODE_TYPES.ArrayExpression))
|
|
422
423
|
);
|
|
423
424
|
}).otherwise(O.none),
|
|
424
425
|
O.exists((x2) => x2.elements.length === 0)
|
|
@@ -432,12 +433,12 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
432
433
|
return;
|
|
433
434
|
}
|
|
434
435
|
const isReferencedToComponentScope = F.pipe(
|
|
435
|
-
$(cb).with({ type:
|
|
436
|
-
if (n2.body.type ===
|
|
436
|
+
$(cb).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n2) => {
|
|
437
|
+
if (n2.body.type === AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
437
438
|
return O.some(n2.body);
|
|
438
439
|
}
|
|
439
440
|
return O.some(n2);
|
|
440
|
-
}).with({ type:
|
|
441
|
+
}).with({ type: AST_NODE_TYPES.FunctionExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n2) => {
|
|
441
442
|
return F.pipe(
|
|
442
443
|
findVariable(n2.name, initialScope),
|
|
443
444
|
O.flatMap(getVariableNode(0)),
|
|
@@ -495,13 +496,13 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
495
496
|
MutRef.update(effectFunctionRef, (current) => current === node ? null : current);
|
|
496
497
|
};
|
|
497
498
|
function isEffectFunction(node) {
|
|
498
|
-
return node.parent?.type ===
|
|
499
|
+
return node.parent?.type === AST_NODE_TYPES.CallExpression && node.parent.callee !== node && isUseEffectCall(node.parent);
|
|
499
500
|
}
|
|
500
501
|
function getCallKind(node) {
|
|
501
502
|
return $(node).when(isUseStateCall2, () => "useState").when(isUseEffectCall, () => "useEffect").when(isSetStateCall, () => "setState").when(isThenCall, () => "then").otherwise(() => "other");
|
|
502
503
|
}
|
|
503
504
|
function getFunctionKind(node) {
|
|
504
|
-
return $(node).when(isEffectFunction, () => "effect").when(
|
|
505
|
+
return $(node).when(isEffectFunction, () => "effect").when(isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
|
|
505
506
|
}
|
|
506
507
|
return {
|
|
507
508
|
":function"(node) {
|
|
@@ -548,10 +549,10 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
548
549
|
}).otherwise(F.constVoid);
|
|
549
550
|
},
|
|
550
551
|
Identifier(node) {
|
|
551
|
-
if (node.parent.type ===
|
|
552
|
+
if (node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) return;
|
|
552
553
|
if (!isIdFromUseStateCall(node)) return;
|
|
553
554
|
switch (node.parent.type) {
|
|
554
|
-
case
|
|
555
|
+
case AST_NODE_TYPES.CallExpression: {
|
|
555
556
|
const [firstArg] = node.parent.arguments;
|
|
556
557
|
if (node !== firstArg) break;
|
|
557
558
|
if (isUseCallbackCall2(node.parent)) {
|
|
@@ -567,9 +568,9 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
567
568
|
}
|
|
568
569
|
break;
|
|
569
570
|
}
|
|
570
|
-
case
|
|
571
|
+
case AST_NODE_TYPES.ArrowFunctionExpression: {
|
|
571
572
|
const parent = node.parent.parent;
|
|
572
|
-
if (parent.type !==
|
|
573
|
+
if (parent.type !== AST_NODE_TYPES.CallExpression) break;
|
|
573
574
|
if (!isUseMemoCall2(parent)) break;
|
|
574
575
|
const maybeVd = traverseUpGuard(parent, isVariableDeclaratorFromHookCall);
|
|
575
576
|
if (O.isNone(maybeVd)) break;
|
|
@@ -583,11 +584,11 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
583
584
|
const getSetStateCalls = (id, initialScope) => {
|
|
584
585
|
const node = O.flatMap(findVariable(id, initialScope), getVariableNode(0)).pipe(O.getOrNull);
|
|
585
586
|
switch (node?.type) {
|
|
586
|
-
case
|
|
587
|
-
case
|
|
588
|
-
case
|
|
587
|
+
case AST_NODE_TYPES.FunctionDeclaration:
|
|
588
|
+
case AST_NODE_TYPES.FunctionExpression:
|
|
589
|
+
case AST_NODE_TYPES.ArrowFunctionExpression:
|
|
589
590
|
return indirectSetStateCalls.get(node) ?? [];
|
|
590
|
-
case
|
|
591
|
+
case AST_NODE_TYPES.CallExpression:
|
|
591
592
|
return indirectSetStateCallsInHooks.get(node) ?? indirectSetStateCallsAsArgs.get(node) ?? [];
|
|
592
593
|
}
|
|
593
594
|
return [];
|
|
@@ -669,13 +670,13 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
669
670
|
MutRef.update(effectFunctionRef, (current) => current === node ? null : current);
|
|
670
671
|
};
|
|
671
672
|
function isEffectFunction(node) {
|
|
672
|
-
return node.parent?.type ===
|
|
673
|
+
return node.parent?.type === AST_NODE_TYPES.CallExpression && node.parent.callee !== node && isUseEffectCall(node.parent);
|
|
673
674
|
}
|
|
674
675
|
function getCallKind(node) {
|
|
675
676
|
return $(node).when(isUseStateCall2, () => "useState").when(isUseEffectCall, () => "useLayoutEffect").when(isSetStateCall, () => "setState").when(isThenCall, () => "then").otherwise(() => "other");
|
|
676
677
|
}
|
|
677
678
|
function getFunctionKind(node) {
|
|
678
|
-
return $(node).when(isEffectFunction, () => "effect").when(
|
|
679
|
+
return $(node).when(isEffectFunction, () => "effect").when(isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
|
|
679
680
|
}
|
|
680
681
|
return {
|
|
681
682
|
":function"(node) {
|
|
@@ -722,10 +723,10 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
722
723
|
}).otherwise(F.constVoid);
|
|
723
724
|
},
|
|
724
725
|
Identifier(node) {
|
|
725
|
-
if (node.parent.type ===
|
|
726
|
+
if (node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) return;
|
|
726
727
|
if (!isIdFromUseStateCall(node)) return;
|
|
727
728
|
switch (node.parent.type) {
|
|
728
|
-
case
|
|
729
|
+
case AST_NODE_TYPES.CallExpression: {
|
|
729
730
|
const [firstArg] = node.parent.arguments;
|
|
730
731
|
if (node !== firstArg) break;
|
|
731
732
|
if (isUseCallbackCall2(node.parent)) {
|
|
@@ -741,9 +742,9 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
741
742
|
}
|
|
742
743
|
break;
|
|
743
744
|
}
|
|
744
|
-
case
|
|
745
|
+
case AST_NODE_TYPES.ArrowFunctionExpression: {
|
|
745
746
|
const parent = node.parent.parent;
|
|
746
|
-
if (parent.type !==
|
|
747
|
+
if (parent.type !== AST_NODE_TYPES.CallExpression) break;
|
|
747
748
|
if (!isUseMemoCall2(parent)) break;
|
|
748
749
|
const maybeVd = traverseUpGuard(parent, isVariableDeclaratorFromHookCall);
|
|
749
750
|
if (O.isNone(maybeVd)) break;
|
|
@@ -757,11 +758,11 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
757
758
|
const getSetStateCalls = (id, initialScope) => {
|
|
758
759
|
const node = O.flatMap(findVariable(id, initialScope), getVariableNode(0)).pipe(O.getOrNull);
|
|
759
760
|
switch (node?.type) {
|
|
760
|
-
case
|
|
761
|
-
case
|
|
762
|
-
case
|
|
761
|
+
case AST_NODE_TYPES.FunctionDeclaration:
|
|
762
|
+
case AST_NODE_TYPES.FunctionExpression:
|
|
763
|
+
case AST_NODE_TYPES.ArrowFunctionExpression:
|
|
763
764
|
return indirectSetStateCalls.get(node) ?? [];
|
|
764
|
-
case
|
|
765
|
+
case AST_NODE_TYPES.CallExpression:
|
|
765
766
|
return indirectSetStateCallsInHooks.get(node) ?? indirectSetStateCallsAsArgs.get(node) ?? [];
|
|
766
767
|
}
|
|
767
768
|
return [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-hooks-extra",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.2-next.2",
|
|
4
4
|
"description": "ESLint React's ESLint plugin for React Hooks related rules.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -45,13 +45,13 @@
|
|
|
45
45
|
"@typescript-eslint/type-utils": "^8.0.1",
|
|
46
46
|
"@typescript-eslint/types": "^8.0.1",
|
|
47
47
|
"@typescript-eslint/utils": "^8.0.1",
|
|
48
|
-
"@eslint-react/
|
|
49
|
-
"@eslint-react/
|
|
50
|
-
"@eslint-react/
|
|
51
|
-
"@eslint-react/
|
|
52
|
-
"@eslint-react/
|
|
53
|
-
"@eslint-react/
|
|
54
|
-
"@eslint-react/var": "1.9.
|
|
48
|
+
"@eslint-react/ast": "1.9.2-next.2",
|
|
49
|
+
"@eslint-react/core": "1.9.2-next.2",
|
|
50
|
+
"@eslint-react/jsx": "1.9.2-next.2",
|
|
51
|
+
"@eslint-react/shared": "1.9.2-next.2",
|
|
52
|
+
"@eslint-react/types": "1.9.2-next.2",
|
|
53
|
+
"@eslint-react/tools": "1.9.2-next.2",
|
|
54
|
+
"@eslint-react/var": "1.9.2-next.2"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/react": "^18.3.3",
|