eslint-plugin-react-hooks-extra 2.0.0-next.4 → 2.0.0-next.44
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 +613 -499
- package/package.json +18 -18
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import * as
|
|
3
|
-
import { identity, getOrElseUpdate, constVoid,
|
|
1
|
+
import * as AST5 from '@eslint-react/ast';
|
|
2
|
+
import * as ER5 from '@eslint-react/core';
|
|
3
|
+
import { identity, getOrElseUpdate, constVoid, not } from '@eslint-react/eff';
|
|
4
4
|
import { getDocsUrl, getSettingsFromContext } from '@eslint-react/shared';
|
|
5
|
-
import * as
|
|
5
|
+
import * as VAR3 from '@eslint-react/var';
|
|
6
6
|
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
7
7
|
import { match } from 'ts-pattern';
|
|
8
8
|
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
@@ -22,296 +22,55 @@ __export(recommended_exports, {
|
|
|
22
22
|
var name = "react-hooks-extra/recommended";
|
|
23
23
|
var rules = {
|
|
24
24
|
"react-hooks-extra/no-direct-set-state-in-use-effect": "warn",
|
|
25
|
-
"react-hooks-extra/no-unnecessary-use-prefix": "warn"
|
|
26
|
-
"react-hooks-extra/prefer-use-state-lazy-initialization": "warn"
|
|
25
|
+
"react-hooks-extra/no-unnecessary-use-prefix": "warn"
|
|
27
26
|
};
|
|
28
27
|
|
|
29
28
|
// package.json
|
|
30
29
|
var name2 = "eslint-plugin-react-hooks-extra";
|
|
31
|
-
var version = "2.0.0-next.
|
|
30
|
+
var version = "2.0.0-next.44";
|
|
32
31
|
var createRule = ESLintUtils.RuleCreator(getDocsUrl("hooks-extra"));
|
|
33
|
-
function isFromHookCall(context, name3, settings, predicate = constTrue) {
|
|
34
|
-
const hookAlias = settings.additionalHooks[name3] ?? [];
|
|
35
|
-
return (topLevelId) => {
|
|
36
|
-
const variable = VAR4.findVariable(topLevelId, context.sourceCode.getScope(topLevelId));
|
|
37
|
-
const variableNode = VAR4.getVariableInitNode(variable, 0);
|
|
38
|
-
if (variableNode == null) return false;
|
|
39
|
-
if (variableNode.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
40
|
-
if (!ER7.isReactHookCallWithNameAlias(context, name3, hookAlias)(variableNode)) return false;
|
|
41
|
-
return predicate(topLevelId, variableNode);
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
function isFromUseStateCall(context, settings) {
|
|
45
|
-
const predicate = (topLevelId, call) => {
|
|
46
|
-
const { parent } = call;
|
|
47
|
-
if (!("id" in parent) || parent.id?.type !== AST_NODE_TYPES.ArrayPattern) {
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
return parent.id.elements.findIndex((e) => e?.type === AST_NODE_TYPES.Identifier && e.name === topLevelId.name) === 1;
|
|
51
|
-
};
|
|
52
|
-
return isFromHookCall(context, "useState", settings, predicate);
|
|
53
|
-
}
|
|
54
|
-
function isFunctionOfImmediatelyInvoked(node) {
|
|
55
|
-
return node.type !== AST_NODE_TYPES.FunctionDeclaration && node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node;
|
|
56
|
-
}
|
|
57
|
-
function isSetFunctionCall(context, settings) {
|
|
58
|
-
const isIdFromUseStateCall = isFromUseStateCall(context, settings);
|
|
59
|
-
return (node) => {
|
|
60
|
-
switch (node.callee.type) {
|
|
61
|
-
// const data = useState();
|
|
62
|
-
// data.at(1)();
|
|
63
|
-
case AST_NODE_TYPES.CallExpression: {
|
|
64
|
-
const { callee } = node.callee;
|
|
65
|
-
if (callee.type !== AST_NODE_TYPES.MemberExpression) {
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
if (!("name" in callee.object)) {
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
const isAt = callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "at";
|
|
72
|
-
const [index] = node.callee.arguments;
|
|
73
|
-
if (!isAt || index == null) {
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
76
|
-
const indexScope = context.sourceCode.getScope(node);
|
|
77
|
-
const indexValue = VAR4.toStaticValue({
|
|
78
|
-
kind: "lazy",
|
|
79
|
-
node: index,
|
|
80
|
-
initialScope: indexScope
|
|
81
|
-
}).value;
|
|
82
|
-
return indexValue === 1 && isIdFromUseStateCall(callee.object);
|
|
83
|
-
}
|
|
84
|
-
// const [data, setData] = useState();
|
|
85
|
-
// setData();
|
|
86
|
-
case AST_NODE_TYPES.Identifier: {
|
|
87
|
-
return isIdFromUseStateCall(node.callee);
|
|
88
|
-
}
|
|
89
|
-
// const data = useState();
|
|
90
|
-
// data[1]();
|
|
91
|
-
case AST_NODE_TYPES.MemberExpression: {
|
|
92
|
-
if (!("name" in node.callee.object)) {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
const property = node.callee.property;
|
|
96
|
-
const propertyScope = context.sourceCode.getScope(node);
|
|
97
|
-
const propertyValue = VAR4.toStaticValue({
|
|
98
|
-
kind: "lazy",
|
|
99
|
-
node: property,
|
|
100
|
-
initialScope: propertyScope
|
|
101
|
-
}).value;
|
|
102
|
-
return propertyValue === 1 && isIdFromUseStateCall(node.callee.object);
|
|
103
|
-
}
|
|
104
|
-
default: {
|
|
105
|
-
return false;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
function isThenCall(node) {
|
|
111
|
-
return node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "then";
|
|
112
|
-
}
|
|
113
|
-
function isVariableDeclaratorFromHookCall(node) {
|
|
114
|
-
if (node.type !== AST_NODE_TYPES.VariableDeclarator) {
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
if (node.id.type !== AST_NODE_TYPES.Identifier) {
|
|
118
|
-
return false;
|
|
119
|
-
}
|
|
120
|
-
if (node.init?.type !== AST_NODE_TYPES.CallExpression) {
|
|
121
|
-
return false;
|
|
122
|
-
}
|
|
123
|
-
switch (node.init.callee.type) {
|
|
124
|
-
case AST_NODE_TYPES.Identifier:
|
|
125
|
-
return ER7.isReactHookName(node.init.callee.name);
|
|
126
|
-
case AST_NODE_TYPES.MemberExpression:
|
|
127
|
-
return node.init.callee.property.type === AST_NODE_TYPES.Identifier && ER7.isReactHookName(node.init.callee.property.name);
|
|
128
|
-
default:
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// src/hooks/use-no-direct-set-state-in-use-effect.ts
|
|
134
|
-
function useNoDirectSetStateInUseEffect(context, options) {
|
|
135
|
-
const { onViolation, useEffectKind } = options;
|
|
136
|
-
const settings = getSettingsFromContext(context);
|
|
137
|
-
const hooks = settings.additionalHooks;
|
|
138
|
-
const getText = (n) => context.sourceCode.getText(n);
|
|
139
|
-
const isUseEffectLikeCall = ER7.isReactHookCallWithNameAlias(context, useEffectKind, hooks[useEffectKind]);
|
|
140
|
-
const isUseStateCall = ER7.isReactHookCallWithNameAlias(context, "useState", hooks.useState);
|
|
141
|
-
const isUseMemoCall = ER7.isReactHookCallWithNameAlias(context, "useMemo", hooks.useMemo);
|
|
142
|
-
const isUseCallbackCall = ER7.isReactHookCallWithNameAlias(context, "useCallback", hooks.useCallback);
|
|
143
|
-
const isSetStateCall = isSetFunctionCall(context, settings);
|
|
144
|
-
const isIdFromUseStateCall = isFromUseStateCall(context, settings);
|
|
145
|
-
const functionEntries = [];
|
|
146
|
-
const setupFunctionRef = { current: null };
|
|
147
|
-
const setupFunctionIdentifiers = [];
|
|
148
|
-
const indFunctionCalls = [];
|
|
149
|
-
const indSetStateCalls = /* @__PURE__ */ new WeakMap();
|
|
150
|
-
const indSetStateCallsInUseEffectArg0 = /* @__PURE__ */ new WeakMap();
|
|
151
|
-
const indSetStateCallsInUseEffectSetup = /* @__PURE__ */ new Map();
|
|
152
|
-
const indSetStateCallsInUseMemoOrCallback = /* @__PURE__ */ new WeakMap();
|
|
153
|
-
const onSetupFunctionEnter = (node) => {
|
|
154
|
-
setupFunctionRef.current = node;
|
|
155
|
-
};
|
|
156
|
-
const onSetupFunctionExit = (node) => {
|
|
157
|
-
if (setupFunctionRef.current === node) {
|
|
158
|
-
setupFunctionRef.current = null;
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
function isFunctionOfUseEffectSetup(node) {
|
|
162
|
-
return node.parent?.type === AST_NODE_TYPES.CallExpression && node.parent.callee !== node && isUseEffectLikeCall(node.parent);
|
|
163
|
-
}
|
|
164
|
-
function getCallName(node) {
|
|
165
|
-
if (node.type === AST_NODE_TYPES.CallExpression) {
|
|
166
|
-
return AST.toString(node.callee, getText);
|
|
167
|
-
}
|
|
168
|
-
return AST.toString(node, getText);
|
|
169
|
-
}
|
|
170
|
-
function getCallKind(node) {
|
|
171
|
-
return match(node).when(isUseStateCall, () => "useState").when(isUseEffectLikeCall, () => useEffectKind).when(isSetStateCall, () => "setState").when(isThenCall, () => "then").otherwise(() => "other");
|
|
172
|
-
}
|
|
173
|
-
function getFunctionKind(node) {
|
|
174
|
-
return match(node).when(isFunctionOfUseEffectSetup, () => "setup").when(isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
|
|
175
|
-
}
|
|
176
|
-
return {
|
|
177
|
-
":function"(node) {
|
|
178
|
-
const kind = getFunctionKind(node);
|
|
179
|
-
functionEntries.push({ kind, node });
|
|
180
|
-
if (kind === "setup") {
|
|
181
|
-
onSetupFunctionEnter(node);
|
|
182
|
-
}
|
|
183
|
-
},
|
|
184
|
-
":function:exit"(node) {
|
|
185
|
-
const { kind } = functionEntries.at(-1) ?? {};
|
|
186
|
-
if (kind === "setup") {
|
|
187
|
-
onSetupFunctionExit(node);
|
|
188
|
-
}
|
|
189
|
-
functionEntries.pop();
|
|
190
|
-
},
|
|
191
|
-
CallExpression(node) {
|
|
192
|
-
const setupFunction = setupFunctionRef.current;
|
|
193
|
-
const pEntry = functionEntries.at(-1);
|
|
194
|
-
if (pEntry == null || pEntry.node.async) {
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
match(getCallKind(node)).with("setState", () => {
|
|
198
|
-
switch (true) {
|
|
199
|
-
case pEntry.node === setupFunction:
|
|
200
|
-
case (pEntry.kind === "immediate" && AST.findParentNode(pEntry.node, AST.isFunction) === setupFunction): {
|
|
201
|
-
onViolation(context, node, {
|
|
202
|
-
name: context.sourceCode.getText(node.callee)
|
|
203
|
-
});
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
default: {
|
|
207
|
-
const vd = AST.findParentNode(node, isVariableDeclaratorFromHookCall);
|
|
208
|
-
if (vd == null) getOrElseUpdate(indSetStateCalls, pEntry.node, () => []).push(node);
|
|
209
|
-
else getOrElseUpdate(indSetStateCallsInUseMemoOrCallback, vd.init, () => []).push(node);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}).with(useEffectKind, () => {
|
|
213
|
-
if (AST.isFunction(node.arguments.at(0))) return;
|
|
214
|
-
setupFunctionIdentifiers.push(...AST.getNestedIdentifiers(node));
|
|
215
|
-
}).with("other", () => {
|
|
216
|
-
if (pEntry.node !== setupFunction) return;
|
|
217
|
-
indFunctionCalls.push(node);
|
|
218
|
-
}).otherwise(constVoid);
|
|
219
|
-
},
|
|
220
|
-
Identifier(node) {
|
|
221
|
-
if (node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) {
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
if (!isIdFromUseStateCall(node)) {
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
switch (node.parent.type) {
|
|
228
|
-
case AST_NODE_TYPES.ArrowFunctionExpression: {
|
|
229
|
-
const parent = node.parent.parent;
|
|
230
|
-
if (parent.type !== AST_NODE_TYPES.CallExpression) {
|
|
231
|
-
break;
|
|
232
|
-
}
|
|
233
|
-
if (!isUseMemoCall(parent)) {
|
|
234
|
-
break;
|
|
235
|
-
}
|
|
236
|
-
const vd = AST.findParentNode(parent, isVariableDeclaratorFromHookCall);
|
|
237
|
-
if (vd != null) {
|
|
238
|
-
getOrElseUpdate(indSetStateCallsInUseEffectArg0, vd.init, () => []).push(node);
|
|
239
|
-
}
|
|
240
|
-
break;
|
|
241
|
-
}
|
|
242
|
-
case AST_NODE_TYPES.CallExpression: {
|
|
243
|
-
if (node !== node.parent.arguments.at(0)) {
|
|
244
|
-
break;
|
|
245
|
-
}
|
|
246
|
-
if (isUseCallbackCall(node.parent)) {
|
|
247
|
-
const vd = AST.findParentNode(node.parent, isVariableDeclaratorFromHookCall);
|
|
248
|
-
if (vd != null) {
|
|
249
|
-
getOrElseUpdate(indSetStateCallsInUseEffectArg0, vd.init, () => []).push(node);
|
|
250
|
-
}
|
|
251
|
-
break;
|
|
252
|
-
}
|
|
253
|
-
if (isUseEffectLikeCall(node.parent)) {
|
|
254
|
-
getOrElseUpdate(indSetStateCallsInUseEffectSetup, node.parent, () => []).push(node);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
},
|
|
259
|
-
"Program:exit"() {
|
|
260
|
-
const getSetStateCalls = (id, initialScope) => {
|
|
261
|
-
const node = VAR4.getVariableInitNode(VAR4.findVariable(id, initialScope), 0);
|
|
262
|
-
switch (node?.type) {
|
|
263
|
-
case AST_NODE_TYPES.ArrowFunctionExpression:
|
|
264
|
-
case AST_NODE_TYPES.FunctionDeclaration:
|
|
265
|
-
case AST_NODE_TYPES.FunctionExpression:
|
|
266
|
-
return indSetStateCalls.get(node) ?? [];
|
|
267
|
-
case AST_NODE_TYPES.CallExpression:
|
|
268
|
-
return indSetStateCallsInUseMemoOrCallback.get(node) ?? indSetStateCallsInUseEffectArg0.get(node) ?? [];
|
|
269
|
-
}
|
|
270
|
-
return [];
|
|
271
|
-
};
|
|
272
|
-
for (const [, calls] of indSetStateCallsInUseEffectSetup) {
|
|
273
|
-
for (const call of calls) {
|
|
274
|
-
onViolation(context, call, { name: call.name });
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
for (const { callee } of indFunctionCalls) {
|
|
278
|
-
if (!("name" in callee)) {
|
|
279
|
-
continue;
|
|
280
|
-
}
|
|
281
|
-
const { name: name3 } = callee;
|
|
282
|
-
const setStateCalls = getSetStateCalls(name3, context.sourceCode.getScope(callee));
|
|
283
|
-
for (const setStateCall of setStateCalls) {
|
|
284
|
-
onViolation(context, setStateCall, {
|
|
285
|
-
name: getCallName(setStateCall)
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
for (const id of setupFunctionIdentifiers) {
|
|
290
|
-
const setStateCalls = getSetStateCalls(id.name, context.sourceCode.getScope(id));
|
|
291
|
-
for (const setStateCall of setStateCalls) {
|
|
292
|
-
onViolation(context, setStateCall, {
|
|
293
|
-
name: getCallName(setStateCall)
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
32
|
|
|
301
|
-
// src/rules/no-
|
|
302
|
-
var RULE_NAME = "no-
|
|
33
|
+
// src/rules-removed/no-unnecessary-use-callback.ts
|
|
34
|
+
var RULE_NAME = "no-unnecessary-use-callback";
|
|
303
35
|
var RULE_FEATURES = [
|
|
304
36
|
"EXP"
|
|
305
37
|
];
|
|
306
|
-
var
|
|
38
|
+
var no_unnecessary_use_callback_default = createRule({
|
|
307
39
|
meta: {
|
|
308
40
|
type: "problem",
|
|
41
|
+
deprecated: {
|
|
42
|
+
deprecatedSince: "2.0.0",
|
|
43
|
+
replacedBy: [
|
|
44
|
+
{
|
|
45
|
+
message: "Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead.",
|
|
46
|
+
plugin: {
|
|
47
|
+
name: "eslint-plugin-react-x",
|
|
48
|
+
url: "https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x"
|
|
49
|
+
},
|
|
50
|
+
rule: {
|
|
51
|
+
name: "no-unnecessary-use-callback",
|
|
52
|
+
url: "https://next.eslint-react.xyz/docs/rules/no-unnecessary-use-callback"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
message: "Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead.",
|
|
57
|
+
plugin: {
|
|
58
|
+
name: "@eslint-react/eslint-plugin",
|
|
59
|
+
url: "https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin"
|
|
60
|
+
},
|
|
61
|
+
rule: {
|
|
62
|
+
name: "no-unnecessary-use-callback",
|
|
63
|
+
url: "https://next.eslint-react.xyz/docs/rules/no-unnecessary-use-callback"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
},
|
|
309
68
|
docs: {
|
|
310
|
-
description: "Disallow
|
|
69
|
+
description: "Disallow unnecessary usage of `useCallback`.",
|
|
311
70
|
[Symbol.for("rule_features")]: RULE_FEATURES
|
|
312
71
|
},
|
|
313
72
|
messages: {
|
|
314
|
-
|
|
73
|
+
noUnnecessaryUseCallback: "An 'useCallback' with empty deps and no references to the component scope may be unnecessary."
|
|
315
74
|
},
|
|
316
75
|
schema: []
|
|
317
76
|
},
|
|
@@ -320,90 +79,140 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
320
79
|
defaultOptions: []
|
|
321
80
|
});
|
|
322
81
|
function create(context) {
|
|
323
|
-
if (
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
82
|
+
if (!context.sourceCode.text.includes("use")) return {};
|
|
83
|
+
const alias = getSettingsFromContext(context).additionalHooks.useCallback ?? [];
|
|
84
|
+
const isUseCallbackCall = ER5.isReactHookCallWithNameAlias(context, "useCallback", alias);
|
|
85
|
+
return {
|
|
86
|
+
CallExpression(node) {
|
|
87
|
+
if (!ER5.isReactHookCall(node)) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const initialScope = context.sourceCode.getScope(node);
|
|
91
|
+
if (!isUseCallbackCall(node)) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const scope = context.sourceCode.getScope(node);
|
|
95
|
+
const component = scope.block;
|
|
96
|
+
if (!AST5.isFunction(component)) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const [arg0, arg1] = node.arguments;
|
|
100
|
+
if (arg0 == null || arg1 == null) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const hasEmptyDeps = match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
|
|
104
|
+
const variable = VAR3.findVariable(n.name, initialScope);
|
|
105
|
+
const variableNode = VAR3.getVariableInitNode(variable, 0);
|
|
106
|
+
if (variableNode?.type !== AST_NODE_TYPES.ArrayExpression) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
return variableNode.elements.length === 0;
|
|
110
|
+
}).otherwise(() => false);
|
|
111
|
+
if (!hasEmptyDeps) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const arg0Node = match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
|
|
115
|
+
if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
116
|
+
return n.body;
|
|
117
|
+
}
|
|
118
|
+
return n;
|
|
119
|
+
}).with({ type: AST_NODE_TYPES.FunctionExpression }, identity).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
|
|
120
|
+
const variable = VAR3.findVariable(n.name, initialScope);
|
|
121
|
+
const variableNode = VAR3.getVariableInitNode(variable, 0);
|
|
122
|
+
if (variableNode?.type !== AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== AST_NODE_TYPES.FunctionExpression) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
return variableNode;
|
|
126
|
+
}).otherwise(() => null);
|
|
127
|
+
if (arg0Node == null) return;
|
|
128
|
+
const arg0NodeScope = context.sourceCode.getScope(arg0Node);
|
|
129
|
+
const arg0NodeReferences = VAR3.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
|
|
130
|
+
const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
|
|
131
|
+
if (!isReferencedToComponentScope) {
|
|
132
|
+
context.report({
|
|
133
|
+
messageId: "noUnnecessaryUseCallback",
|
|
134
|
+
node
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
361
139
|
}
|
|
362
|
-
var
|
|
363
|
-
var
|
|
140
|
+
var RULE_NAME2 = "no-unnecessary-use-memo";
|
|
141
|
+
var RULE_FEATURES2 = [
|
|
364
142
|
"EXP"
|
|
365
143
|
];
|
|
366
|
-
var
|
|
144
|
+
var no_unnecessary_use_memo_default = createRule({
|
|
367
145
|
meta: {
|
|
368
146
|
type: "problem",
|
|
147
|
+
deprecated: {
|
|
148
|
+
deprecatedSince: "2.0.0",
|
|
149
|
+
replacedBy: [
|
|
150
|
+
{
|
|
151
|
+
message: "Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead.",
|
|
152
|
+
plugin: {
|
|
153
|
+
name: "eslint-plugin-react-x",
|
|
154
|
+
url: "https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x"
|
|
155
|
+
},
|
|
156
|
+
rule: {
|
|
157
|
+
name: "no-unnecessary-use-memo",
|
|
158
|
+
url: "https://next.eslint-react.xyz/docs/rules/no-unnecessary-use-memo"
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
message: "Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead.",
|
|
163
|
+
plugin: {
|
|
164
|
+
name: "@eslint-react/eslint-plugin",
|
|
165
|
+
url: "https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin"
|
|
166
|
+
},
|
|
167
|
+
rule: {
|
|
168
|
+
name: "no-unnecessary-use-memo",
|
|
169
|
+
url: "https://next.eslint-react.xyz/docs/rules/no-unnecessary-use-memo"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
]
|
|
173
|
+
},
|
|
369
174
|
docs: {
|
|
370
|
-
description: "Disallow unnecessary usage of `
|
|
371
|
-
[Symbol.for("rule_features")]:
|
|
175
|
+
description: "Disallow unnecessary usage of `useMemo`.",
|
|
176
|
+
[Symbol.for("rule_features")]: RULE_FEATURES2
|
|
372
177
|
},
|
|
373
178
|
messages: {
|
|
374
|
-
|
|
179
|
+
noUnnecessaryUseMemo: "An 'useMemo' with empty deps and no references to the component scope may be unnecessary."
|
|
375
180
|
},
|
|
376
181
|
schema: []
|
|
377
182
|
},
|
|
378
|
-
name:
|
|
379
|
-
create:
|
|
183
|
+
name: RULE_NAME2,
|
|
184
|
+
create: create2,
|
|
380
185
|
defaultOptions: []
|
|
381
186
|
});
|
|
382
|
-
function
|
|
187
|
+
function create2(context) {
|
|
383
188
|
if (!context.sourceCode.text.includes("use")) return {};
|
|
384
|
-
const alias = getSettingsFromContext(context).additionalHooks.
|
|
385
|
-
const
|
|
189
|
+
const alias = getSettingsFromContext(context).additionalHooks.useMemo ?? [];
|
|
190
|
+
const isUseMemoCall = ER5.isReactHookCallWithNameAlias(context, "useMemo", alias);
|
|
386
191
|
return {
|
|
387
192
|
CallExpression(node) {
|
|
388
|
-
if (!
|
|
193
|
+
if (!ER5.isReactHookCall(node)) {
|
|
389
194
|
return;
|
|
390
195
|
}
|
|
391
196
|
const initialScope = context.sourceCode.getScope(node);
|
|
392
|
-
if (!
|
|
197
|
+
if (!isUseMemoCall(node)) {
|
|
393
198
|
return;
|
|
394
199
|
}
|
|
395
200
|
const scope = context.sourceCode.getScope(node);
|
|
396
201
|
const component = scope.block;
|
|
397
|
-
if (!
|
|
202
|
+
if (!AST5.isFunction(component)) {
|
|
398
203
|
return;
|
|
399
204
|
}
|
|
400
205
|
const [arg0, arg1] = node.arguments;
|
|
401
206
|
if (arg0 == null || arg1 == null) {
|
|
402
207
|
return;
|
|
403
208
|
}
|
|
209
|
+
const hasCallInArg0 = AST5.isFunction(arg0) && [...AST5.getNestedCallExpressions(arg0.body), ...AST5.getNestedNewExpressions(arg0.body)].length > 0;
|
|
210
|
+
if (hasCallInArg0) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
404
213
|
const hasEmptyDeps = match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
|
|
405
|
-
const variable =
|
|
406
|
-
const variableNode =
|
|
214
|
+
const variable = VAR3.findVariable(n.name, initialScope);
|
|
215
|
+
const variableNode = VAR3.getVariableInitNode(variable, 0);
|
|
407
216
|
if (variableNode?.type !== AST_NODE_TYPES.ArrayExpression) {
|
|
408
217
|
return false;
|
|
409
218
|
}
|
|
@@ -418,8 +227,8 @@ function create3(context) {
|
|
|
418
227
|
}
|
|
419
228
|
return n;
|
|
420
229
|
}).with({ type: AST_NODE_TYPES.FunctionExpression }, identity).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
|
|
421
|
-
const variable =
|
|
422
|
-
const variableNode =
|
|
230
|
+
const variable = VAR3.findVariable(n.name, initialScope);
|
|
231
|
+
const variableNode = VAR3.getVariableInitNode(variable, 0);
|
|
423
232
|
if (variableNode?.type !== AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== AST_NODE_TYPES.FunctionExpression) {
|
|
424
233
|
return null;
|
|
425
234
|
}
|
|
@@ -427,117 +236,482 @@ function create3(context) {
|
|
|
427
236
|
}).otherwise(() => null);
|
|
428
237
|
if (arg0Node == null) return;
|
|
429
238
|
const arg0NodeScope = context.sourceCode.getScope(arg0Node);
|
|
430
|
-
const arg0NodeReferences =
|
|
239
|
+
const arg0NodeReferences = VAR3.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
|
|
431
240
|
const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
|
|
432
241
|
if (!isReferencedToComponentScope) {
|
|
433
242
|
context.report({
|
|
434
|
-
messageId: "
|
|
243
|
+
messageId: "noUnnecessaryUseMemo",
|
|
435
244
|
node
|
|
436
245
|
});
|
|
437
246
|
}
|
|
438
247
|
}
|
|
439
248
|
};
|
|
440
249
|
}
|
|
441
|
-
var
|
|
250
|
+
var RULE_NAME3 = "no-unnecessary-use-prefix";
|
|
251
|
+
var RULE_FEATURES3 = [];
|
|
252
|
+
var WELL_KNOWN_HOOKS = [
|
|
253
|
+
"useMDXComponents"
|
|
254
|
+
];
|
|
255
|
+
function containsUseComments(context, node) {
|
|
256
|
+
return context.sourceCode.getCommentsInside(node).some(({ value }) => /use\([\s\S]*?\)/u.test(value) || /use[A-Z0-9]\w*\([\s\S]*?\)/u.test(value));
|
|
257
|
+
}
|
|
258
|
+
var no_unnecessary_use_prefix_default = createRule({
|
|
259
|
+
meta: {
|
|
260
|
+
type: "problem",
|
|
261
|
+
deprecated: {
|
|
262
|
+
deprecatedSince: "2.0.0",
|
|
263
|
+
replacedBy: [
|
|
264
|
+
{
|
|
265
|
+
message: "Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead.",
|
|
266
|
+
plugin: {
|
|
267
|
+
name: "eslint-plugin-react-x",
|
|
268
|
+
url: "https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x"
|
|
269
|
+
},
|
|
270
|
+
rule: {
|
|
271
|
+
name: "no-unnecessary-use-prefix",
|
|
272
|
+
url: "https://next.eslint-react.xyz/docs/rules/no-unnecessary-use-prefix"
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
message: "Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead.",
|
|
277
|
+
plugin: {
|
|
278
|
+
name: "@eslint-react/eslint-plugin",
|
|
279
|
+
url: "https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin"
|
|
280
|
+
},
|
|
281
|
+
rule: {
|
|
282
|
+
name: "no-unnecessary-use-prefix",
|
|
283
|
+
url: "https://next.eslint-react.xyz/docs/rules/no-unnecessary-use-prefix"
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
]
|
|
287
|
+
},
|
|
288
|
+
docs: {
|
|
289
|
+
description: "Enforces that a function with the `use` prefix should use at least one Hook inside of it.",
|
|
290
|
+
[Symbol.for("rule_features")]: RULE_FEATURES3
|
|
291
|
+
},
|
|
292
|
+
messages: {
|
|
293
|
+
noUnnecessaryUsePrefix: "If your function doesn't call any Hooks, avoid the 'use' prefix. Instead, write it as a regular function without the 'use' prefix."
|
|
294
|
+
},
|
|
295
|
+
schema: []
|
|
296
|
+
},
|
|
297
|
+
name: RULE_NAME3,
|
|
298
|
+
create: create3,
|
|
299
|
+
defaultOptions: []
|
|
300
|
+
});
|
|
301
|
+
function create3(context) {
|
|
302
|
+
const { ctx, listeners } = ER5.useHookCollector();
|
|
303
|
+
return {
|
|
304
|
+
...listeners,
|
|
305
|
+
"Program:exit"(program) {
|
|
306
|
+
const allHooks = ctx.getAllHooks(program);
|
|
307
|
+
for (const { id, name: name3, node, hookCalls } of allHooks.values()) {
|
|
308
|
+
if (WELL_KNOWN_HOOKS.includes(name3)) {
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
if (AST5.isEmptyFunction(node)) {
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
if (hookCalls.length > 0) {
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
if (containsUseComments(context, node)) {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
if (id != null) {
|
|
321
|
+
context.report({
|
|
322
|
+
messageId: "noUnnecessaryUsePrefix",
|
|
323
|
+
data: {
|
|
324
|
+
name: name3
|
|
325
|
+
},
|
|
326
|
+
loc: getPreferredLoc(context, id)
|
|
327
|
+
});
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
context.report({
|
|
331
|
+
messageId: "noUnnecessaryUsePrefix",
|
|
332
|
+
node,
|
|
333
|
+
data: {
|
|
334
|
+
name: name3
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
function getPreferredLoc(context, id) {
|
|
342
|
+
if (AST5.isMultiLine(id)) return id.loc;
|
|
343
|
+
if (!context.sourceCode.getText(id).startsWith("use")) return id.loc;
|
|
344
|
+
return {
|
|
345
|
+
end: {
|
|
346
|
+
column: id.loc.start.column + 3,
|
|
347
|
+
line: id.loc.start.line
|
|
348
|
+
},
|
|
349
|
+
start: {
|
|
350
|
+
column: id.loc.start.column,
|
|
351
|
+
line: id.loc.start.line
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
var RULE_NAME4 = "prefer-use-state-lazy-initialization";
|
|
442
356
|
var RULE_FEATURES4 = [
|
|
443
357
|
"EXP"
|
|
444
358
|
];
|
|
445
|
-
var
|
|
359
|
+
var ALLOW_LIST = [
|
|
360
|
+
"Boolean",
|
|
361
|
+
"String",
|
|
362
|
+
"Number"
|
|
363
|
+
];
|
|
364
|
+
var prefer_use_state_lazy_initialization_default = createRule({
|
|
446
365
|
meta: {
|
|
447
366
|
type: "problem",
|
|
367
|
+
deprecated: {
|
|
368
|
+
deprecatedSince: "2.0.0",
|
|
369
|
+
replacedBy: [
|
|
370
|
+
{
|
|
371
|
+
message: "Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead.",
|
|
372
|
+
plugin: {
|
|
373
|
+
name: "eslint-plugin-react-x",
|
|
374
|
+
url: "https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x"
|
|
375
|
+
},
|
|
376
|
+
rule: {
|
|
377
|
+
name: "prefer-use-state-lazy-initialization",
|
|
378
|
+
url: "https://next.eslint-react.xyz/docs/rules/prefer-use-state-lazy-initialization"
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
message: "Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead.",
|
|
383
|
+
plugin: {
|
|
384
|
+
name: "@eslint-react/eslint-plugin",
|
|
385
|
+
url: "https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin"
|
|
386
|
+
},
|
|
387
|
+
rule: {
|
|
388
|
+
name: "prefer-use-state-lazy-initialization",
|
|
389
|
+
url: "https://next.eslint-react.xyz/docs/rules/prefer-use-state-lazy-initialization"
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
]
|
|
393
|
+
},
|
|
448
394
|
docs: {
|
|
449
|
-
description: "
|
|
395
|
+
description: "Enforces function calls made inside `useState` to be wrapped in an `initializer function`.",
|
|
450
396
|
[Symbol.for("rule_features")]: RULE_FEATURES4
|
|
451
397
|
},
|
|
452
398
|
messages: {
|
|
453
|
-
|
|
399
|
+
preferUseStateLazyInitialization: "To prevent re-computation, consider using lazy initial state for useState calls that involve function calls. Ex: 'useState(() => getValue())'."
|
|
400
|
+
},
|
|
401
|
+
schema: []
|
|
402
|
+
},
|
|
403
|
+
name: RULE_NAME4,
|
|
404
|
+
create: create4,
|
|
405
|
+
defaultOptions: []
|
|
406
|
+
});
|
|
407
|
+
function create4(context) {
|
|
408
|
+
const alias = getSettingsFromContext(context).additionalHooks.useState ?? [];
|
|
409
|
+
const isUseStateCall = ER5.isReactHookCallWithNameAlias(context, "useState", alias);
|
|
410
|
+
return {
|
|
411
|
+
CallExpression(node) {
|
|
412
|
+
if (!ER5.isReactHookCall(node)) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
if (!isUseStateCall(node)) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
const [useStateInput] = node.arguments;
|
|
419
|
+
if (useStateInput == null) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
for (const expr of AST5.getNestedNewExpressions(useStateInput)) {
|
|
423
|
+
if (!("name" in expr.callee)) continue;
|
|
424
|
+
if (ALLOW_LIST.includes(expr.callee.name)) continue;
|
|
425
|
+
if (AST5.findParentNode(expr, (n) => ER5.isUseCall(context, n)) != null) continue;
|
|
426
|
+
context.report({
|
|
427
|
+
messageId: "preferUseStateLazyInitialization",
|
|
428
|
+
node: expr
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
for (const expr of AST5.getNestedCallExpressions(useStateInput)) {
|
|
432
|
+
if (!("name" in expr.callee)) continue;
|
|
433
|
+
if (ER5.isReactHookName(expr.callee.name)) continue;
|
|
434
|
+
if (ALLOW_LIST.includes(expr.callee.name)) continue;
|
|
435
|
+
if (AST5.findParentNode(expr, (n) => ER5.isUseCall(context, n)) != null) continue;
|
|
436
|
+
context.report({
|
|
437
|
+
messageId: "preferUseStateLazyInitialization",
|
|
438
|
+
node: expr
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
function useNoDirectSetStateInUseEffect(context, options) {
|
|
445
|
+
const { onViolation, useEffectKind } = options;
|
|
446
|
+
const settings = getSettingsFromContext(context);
|
|
447
|
+
const hooks = settings.additionalHooks;
|
|
448
|
+
const getText = (n) => context.sourceCode.getText(n);
|
|
449
|
+
const isUseEffectLikeCall = ER5.isReactHookCallWithNameAlias(context, useEffectKind, hooks[useEffectKind]);
|
|
450
|
+
const isUseStateCall = ER5.isReactHookCallWithNameAlias(context, "useState", hooks.useState);
|
|
451
|
+
const isUseMemoCall = ER5.isReactHookCallWithNameAlias(context, "useMemo", hooks.useMemo);
|
|
452
|
+
const isUseCallbackCall = ER5.isReactHookCallWithNameAlias(context, "useCallback", hooks.useCallback);
|
|
453
|
+
const functionEntries = [];
|
|
454
|
+
const setupFunctionRef = { current: null };
|
|
455
|
+
const setupFunctionIdentifiers = [];
|
|
456
|
+
const indFunctionCalls = [];
|
|
457
|
+
const indSetStateCalls = /* @__PURE__ */ new WeakMap();
|
|
458
|
+
const indSetStateCallsInUseEffectArg0 = /* @__PURE__ */ new WeakMap();
|
|
459
|
+
const indSetStateCallsInUseEffectSetup = /* @__PURE__ */ new Map();
|
|
460
|
+
const indSetStateCallsInUseMemoOrCallback = /* @__PURE__ */ new WeakMap();
|
|
461
|
+
const onSetupFunctionEnter = (node) => {
|
|
462
|
+
setupFunctionRef.current = node;
|
|
463
|
+
};
|
|
464
|
+
const onSetupFunctionExit = (node) => {
|
|
465
|
+
if (setupFunctionRef.current === node) {
|
|
466
|
+
setupFunctionRef.current = null;
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
function isFunctionOfUseEffectSetup(node) {
|
|
470
|
+
return node.parent?.type === AST_NODE_TYPES.CallExpression && node.parent.callee !== node && isUseEffectLikeCall(node.parent);
|
|
471
|
+
}
|
|
472
|
+
function getCallName(node) {
|
|
473
|
+
if (node.type === AST_NODE_TYPES.CallExpression) {
|
|
474
|
+
return AST5.toStringFormat(node.callee, getText);
|
|
475
|
+
}
|
|
476
|
+
return AST5.toStringFormat(node, getText);
|
|
477
|
+
}
|
|
478
|
+
function getCallKind(node) {
|
|
479
|
+
return match(node).when(isUseStateCall, () => "useState").when(isUseEffectLikeCall, () => useEffectKind).when(isSetStateCall, () => "setState").when(AST5.isThenCall, () => "then").otherwise(() => "other");
|
|
480
|
+
}
|
|
481
|
+
function getFunctionKind(node) {
|
|
482
|
+
const parent = AST5.findParentNode(node, not(AST5.isTypeExpression)) ?? node.parent;
|
|
483
|
+
switch (true) {
|
|
484
|
+
case node.async:
|
|
485
|
+
case (parent.type === AST_NODE_TYPES.CallExpression && AST5.isThenCall(parent)):
|
|
486
|
+
return "deferred";
|
|
487
|
+
case (node.type !== AST_NODE_TYPES.FunctionDeclaration && parent.type === AST_NODE_TYPES.CallExpression && parent.callee === node):
|
|
488
|
+
return "immediate";
|
|
489
|
+
case isFunctionOfUseEffectSetup(node):
|
|
490
|
+
return "setup";
|
|
491
|
+
default:
|
|
492
|
+
return "other";
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
function isIdFromUseStateCall(topLevelId, at) {
|
|
496
|
+
const variable = VAR3.findVariable(topLevelId, context.sourceCode.getScope(topLevelId));
|
|
497
|
+
const variableNode = VAR3.getVariableInitNode(variable, 0);
|
|
498
|
+
if (variableNode == null) return false;
|
|
499
|
+
if (variableNode.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
500
|
+
if (!ER5.isReactHookCallWithNameAlias(context, "useState", hooks.useState)(variableNode)) return false;
|
|
501
|
+
const variableNodeParent = variableNode.parent;
|
|
502
|
+
if (!("id" in variableNodeParent) || variableNodeParent.id?.type !== AST_NODE_TYPES.ArrayPattern) {
|
|
503
|
+
return true;
|
|
504
|
+
}
|
|
505
|
+
return variableNodeParent.id.elements.findIndex((e) => e?.type === AST_NODE_TYPES.Identifier && e.name === topLevelId.name) === at;
|
|
506
|
+
}
|
|
507
|
+
function isSetStateCall(node) {
|
|
508
|
+
switch (node.callee.type) {
|
|
509
|
+
// const data = useState();
|
|
510
|
+
// data.at(1)();
|
|
511
|
+
case AST_NODE_TYPES.CallExpression: {
|
|
512
|
+
const { callee } = node.callee;
|
|
513
|
+
if (callee.type !== AST_NODE_TYPES.MemberExpression) {
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
516
|
+
if (!("name" in callee.object)) {
|
|
517
|
+
return false;
|
|
518
|
+
}
|
|
519
|
+
const isAt = callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "at";
|
|
520
|
+
const [index] = node.callee.arguments;
|
|
521
|
+
if (!isAt || index == null) {
|
|
522
|
+
return false;
|
|
523
|
+
}
|
|
524
|
+
const indexScope = context.sourceCode.getScope(node);
|
|
525
|
+
const indexValue = VAR3.toStaticValue({
|
|
526
|
+
kind: "lazy",
|
|
527
|
+
node: index,
|
|
528
|
+
initialScope: indexScope
|
|
529
|
+
}).value;
|
|
530
|
+
return indexValue === 1 && isIdFromUseStateCall(callee.object);
|
|
531
|
+
}
|
|
532
|
+
// const [data, setData] = useState();
|
|
533
|
+
// setData();
|
|
534
|
+
case AST_NODE_TYPES.Identifier: {
|
|
535
|
+
return isIdFromUseStateCall(node.callee, 1);
|
|
536
|
+
}
|
|
537
|
+
// const data = useState();
|
|
538
|
+
// data[1]();
|
|
539
|
+
case AST_NODE_TYPES.MemberExpression: {
|
|
540
|
+
if (!("name" in node.callee.object)) {
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
const property = node.callee.property;
|
|
544
|
+
const propertyScope = context.sourceCode.getScope(node);
|
|
545
|
+
const propertyValue = VAR3.toStaticValue({
|
|
546
|
+
kind: "lazy",
|
|
547
|
+
node: property,
|
|
548
|
+
initialScope: propertyScope
|
|
549
|
+
}).value;
|
|
550
|
+
return propertyValue === 1 && isIdFromUseStateCall(node.callee.object, 1);
|
|
551
|
+
}
|
|
552
|
+
default: {
|
|
553
|
+
return false;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return {
|
|
558
|
+
":function"(node) {
|
|
559
|
+
const kind = getFunctionKind(node);
|
|
560
|
+
functionEntries.push({ kind, node });
|
|
561
|
+
if (kind === "setup") {
|
|
562
|
+
onSetupFunctionEnter(node);
|
|
563
|
+
}
|
|
564
|
+
},
|
|
565
|
+
":function:exit"(node) {
|
|
566
|
+
const { kind } = functionEntries.at(-1) ?? {};
|
|
567
|
+
if (kind === "setup") {
|
|
568
|
+
onSetupFunctionExit(node);
|
|
569
|
+
}
|
|
570
|
+
functionEntries.pop();
|
|
454
571
|
},
|
|
455
|
-
schema: []
|
|
456
|
-
},
|
|
457
|
-
name: RULE_NAME4,
|
|
458
|
-
create: create4,
|
|
459
|
-
defaultOptions: []
|
|
460
|
-
});
|
|
461
|
-
function create4(context) {
|
|
462
|
-
if (!context.sourceCode.text.includes("use")) return {};
|
|
463
|
-
const alias = getSettingsFromContext(context).additionalHooks.useMemo ?? [];
|
|
464
|
-
const isUseMemoCall = ER7.isReactHookCallWithNameAlias(context, "useMemo", alias);
|
|
465
|
-
return {
|
|
466
572
|
CallExpression(node) {
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
471
|
-
if (!isUseMemoCall(node)) {
|
|
573
|
+
const setupFunction = setupFunctionRef.current;
|
|
574
|
+
const pEntry = functionEntries.at(-1);
|
|
575
|
+
if (pEntry == null || pEntry.node.async) {
|
|
472
576
|
return;
|
|
473
577
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
578
|
+
match(getCallKind(node)).with("setState", () => {
|
|
579
|
+
switch (true) {
|
|
580
|
+
case pEntry.kind === "deferred":
|
|
581
|
+
case pEntry.node.async:
|
|
582
|
+
break;
|
|
583
|
+
case pEntry.node === setupFunction:
|
|
584
|
+
case (pEntry.kind === "immediate" && AST5.findParentNode(pEntry.node, AST5.isFunction) === setupFunction): {
|
|
585
|
+
onViolation(context, node, {
|
|
586
|
+
name: context.sourceCode.getText(node.callee)
|
|
587
|
+
});
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
default: {
|
|
591
|
+
const vd = AST5.findParentNode(node, isVariableDeclaratorFromHookCall);
|
|
592
|
+
if (vd == null) getOrElseUpdate(indSetStateCalls, pEntry.node, () => []).push(node);
|
|
593
|
+
else getOrElseUpdate(indSetStateCallsInUseMemoOrCallback, vd.init, () => []).push(node);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}).with(useEffectKind, () => {
|
|
597
|
+
if (AST5.isFunction(node.arguments.at(0))) return;
|
|
598
|
+
setupFunctionIdentifiers.push(...AST5.getNestedIdentifiers(node));
|
|
599
|
+
}).with("other", () => {
|
|
600
|
+
if (pEntry.node !== setupFunction) return;
|
|
601
|
+
indFunctionCalls.push(node);
|
|
602
|
+
}).otherwise(constVoid);
|
|
603
|
+
},
|
|
604
|
+
Identifier(node) {
|
|
605
|
+
if (node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) {
|
|
477
606
|
return;
|
|
478
607
|
}
|
|
479
|
-
|
|
480
|
-
if (arg0 == null || arg1 == null) {
|
|
608
|
+
if (!isIdFromUseStateCall(node, 1)) {
|
|
481
609
|
return;
|
|
482
610
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
611
|
+
switch (node.parent.type) {
|
|
612
|
+
case AST_NODE_TYPES.ArrowFunctionExpression: {
|
|
613
|
+
const parent = node.parent.parent;
|
|
614
|
+
if (parent.type !== AST_NODE_TYPES.CallExpression) {
|
|
615
|
+
break;
|
|
616
|
+
}
|
|
617
|
+
if (!isUseMemoCall(parent)) {
|
|
618
|
+
break;
|
|
619
|
+
}
|
|
620
|
+
const vd = AST5.findParentNode(parent, isVariableDeclaratorFromHookCall);
|
|
621
|
+
if (vd != null) {
|
|
622
|
+
getOrElseUpdate(indSetStateCallsInUseEffectArg0, vd.init, () => []).push(node);
|
|
623
|
+
}
|
|
624
|
+
break;
|
|
625
|
+
}
|
|
626
|
+
case AST_NODE_TYPES.CallExpression: {
|
|
627
|
+
if (node !== node.parent.arguments.at(0)) {
|
|
628
|
+
break;
|
|
629
|
+
}
|
|
630
|
+
if (isUseCallbackCall(node.parent)) {
|
|
631
|
+
const vd = AST5.findParentNode(node.parent, isVariableDeclaratorFromHookCall);
|
|
632
|
+
if (vd != null) {
|
|
633
|
+
getOrElseUpdate(indSetStateCallsInUseEffectArg0, vd.init, () => []).push(node);
|
|
634
|
+
}
|
|
635
|
+
break;
|
|
636
|
+
}
|
|
637
|
+
if (isUseEffectLikeCall(node.parent)) {
|
|
638
|
+
getOrElseUpdate(indSetStateCallsInUseEffectSetup, node.parent, () => []).push(node);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
486
641
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
642
|
+
},
|
|
643
|
+
"Program:exit"() {
|
|
644
|
+
const getSetStateCalls = (id, initialScope) => {
|
|
645
|
+
const node = VAR3.getVariableInitNode(VAR3.findVariable(id, initialScope), 0);
|
|
646
|
+
switch (node?.type) {
|
|
647
|
+
case AST_NODE_TYPES.ArrowFunctionExpression:
|
|
648
|
+
case AST_NODE_TYPES.FunctionDeclaration:
|
|
649
|
+
case AST_NODE_TYPES.FunctionExpression:
|
|
650
|
+
return indSetStateCalls.get(node) ?? [];
|
|
651
|
+
case AST_NODE_TYPES.CallExpression:
|
|
652
|
+
return indSetStateCallsInUseMemoOrCallback.get(node) ?? indSetStateCallsInUseEffectArg0.get(node) ?? [];
|
|
653
|
+
}
|
|
654
|
+
return [];
|
|
655
|
+
};
|
|
656
|
+
for (const [, calls] of indSetStateCallsInUseEffectSetup) {
|
|
657
|
+
for (const call of calls) {
|
|
658
|
+
onViolation(context, call, { name: call.name });
|
|
492
659
|
}
|
|
493
|
-
return variableNode.elements.length === 0;
|
|
494
|
-
}).otherwise(() => false);
|
|
495
|
-
if (!hasEmptyDeps) {
|
|
496
|
-
return;
|
|
497
660
|
}
|
|
498
|
-
const
|
|
499
|
-
if (
|
|
500
|
-
|
|
661
|
+
for (const { callee } of indFunctionCalls) {
|
|
662
|
+
if (!("name" in callee)) {
|
|
663
|
+
continue;
|
|
501
664
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
665
|
+
const { name: name3 } = callee;
|
|
666
|
+
const setStateCalls = getSetStateCalls(name3, context.sourceCode.getScope(callee));
|
|
667
|
+
for (const setStateCall of setStateCalls) {
|
|
668
|
+
onViolation(context, setStateCall, {
|
|
669
|
+
name: getCallName(setStateCall)
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
for (const id of setupFunctionIdentifiers) {
|
|
674
|
+
const setStateCalls = getSetStateCalls(id.name, context.sourceCode.getScope(id));
|
|
675
|
+
for (const setStateCall of setStateCalls) {
|
|
676
|
+
onViolation(context, setStateCall, {
|
|
677
|
+
name: getCallName(setStateCall)
|
|
678
|
+
});
|
|
508
679
|
}
|
|
509
|
-
return variableNode;
|
|
510
|
-
}).otherwise(() => null);
|
|
511
|
-
if (arg0Node == null) return;
|
|
512
|
-
const arg0NodeScope = context.sourceCode.getScope(arg0Node);
|
|
513
|
-
const arg0NodeReferences = VAR4.getChidScopes(arg0NodeScope).flatMap((x) => x.references);
|
|
514
|
-
const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
|
|
515
|
-
if (!isReferencedToComponentScope) {
|
|
516
|
-
context.report({
|
|
517
|
-
messageId: "noUnnecessaryUseMemo",
|
|
518
|
-
node
|
|
519
|
-
});
|
|
520
680
|
}
|
|
521
681
|
}
|
|
522
682
|
};
|
|
523
683
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
684
|
+
function isInitFromHookCall(init) {
|
|
685
|
+
if (init?.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
686
|
+
switch (init.callee.type) {
|
|
687
|
+
case AST_NODE_TYPES.Identifier:
|
|
688
|
+
return ER5.isReactHookName(init.callee.name);
|
|
689
|
+
case AST_NODE_TYPES.MemberExpression:
|
|
690
|
+
return init.callee.property.type === AST_NODE_TYPES.Identifier && ER5.isReactHookName(init.callee.property.name);
|
|
691
|
+
default:
|
|
692
|
+
return false;
|
|
693
|
+
}
|
|
531
694
|
}
|
|
532
|
-
|
|
695
|
+
function isVariableDeclaratorFromHookCall(node) {
|
|
696
|
+
if (node.type !== AST_NODE_TYPES.VariableDeclarator) return false;
|
|
697
|
+
if (node.id.type !== AST_NODE_TYPES.Identifier) return false;
|
|
698
|
+
return isInitFromHookCall(node.init);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// src/rules/no-direct-set-state-in-use-effect.ts
|
|
702
|
+
var RULE_NAME5 = "no-direct-set-state-in-use-effect";
|
|
703
|
+
var RULE_FEATURES5 = [
|
|
704
|
+
"EXP"
|
|
705
|
+
];
|
|
706
|
+
var no_direct_set_state_in_use_effect_default = createRule({
|
|
533
707
|
meta: {
|
|
534
708
|
type: "problem",
|
|
535
709
|
docs: {
|
|
536
|
-
description: "
|
|
710
|
+
description: "Disallow direct calls to the `set` function of `useState` in `useEffect`.",
|
|
537
711
|
[Symbol.for("rule_features")]: RULE_FEATURES5
|
|
538
712
|
},
|
|
539
713
|
messages: {
|
|
540
|
-
|
|
714
|
+
noDirectSetStateInUseEffect: "Do not call the 'set' function '{{name}}' of 'useState' directly in 'useEffect'."
|
|
541
715
|
},
|
|
542
716
|
schema: []
|
|
543
717
|
},
|
|
@@ -546,77 +720,29 @@ var no_unnecessary_use_prefix_default = createRule({
|
|
|
546
720
|
defaultOptions: []
|
|
547
721
|
});
|
|
548
722
|
function create5(context) {
|
|
549
|
-
|
|
550
|
-
return {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
const allHooks = ctx.getAllHooks(program);
|
|
554
|
-
for (const { id, name: name3, node, hookCalls } of allHooks.values()) {
|
|
555
|
-
if (WELL_KNOWN_HOOKS.includes(name3)) {
|
|
556
|
-
continue;
|
|
557
|
-
}
|
|
558
|
-
if (AST.isEmptyFunction(node)) {
|
|
559
|
-
continue;
|
|
560
|
-
}
|
|
561
|
-
if (hookCalls.length > 0) {
|
|
562
|
-
continue;
|
|
563
|
-
}
|
|
564
|
-
if (containsUseComments(context, node)) {
|
|
565
|
-
continue;
|
|
566
|
-
}
|
|
567
|
-
if (id != null) {
|
|
568
|
-
context.report({
|
|
569
|
-
messageId: "noUnnecessaryUsePrefix",
|
|
570
|
-
data: {
|
|
571
|
-
name: name3
|
|
572
|
-
},
|
|
573
|
-
loc: getPreferredLoc(context, id)
|
|
574
|
-
});
|
|
575
|
-
continue;
|
|
576
|
-
}
|
|
577
|
-
context.report({
|
|
578
|
-
messageId: "noUnnecessaryUsePrefix",
|
|
579
|
-
node,
|
|
580
|
-
data: {
|
|
581
|
-
name: name3
|
|
582
|
-
}
|
|
583
|
-
});
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
};
|
|
587
|
-
}
|
|
588
|
-
function getPreferredLoc(context, id) {
|
|
589
|
-
if (AST.isMultiLine(id)) return id.loc;
|
|
590
|
-
if (!context.sourceCode.getText(id).startsWith("use")) return id.loc;
|
|
591
|
-
return {
|
|
592
|
-
end: {
|
|
593
|
-
column: id.loc.start.column + 3,
|
|
594
|
-
line: id.loc.start.line
|
|
723
|
+
if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
|
|
724
|
+
return useNoDirectSetStateInUseEffect(context, {
|
|
725
|
+
onViolation(ctx, node, data) {
|
|
726
|
+
ctx.report({ messageId: "noDirectSetStateInUseEffect", node, data });
|
|
595
727
|
},
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
line: id.loc.start.line
|
|
599
|
-
}
|
|
600
|
-
};
|
|
728
|
+
useEffectKind: "useEffect"
|
|
729
|
+
});
|
|
601
730
|
}
|
|
602
|
-
|
|
731
|
+
|
|
732
|
+
// src/rules/no-direct-set-state-in-use-layout-effect.ts
|
|
733
|
+
var RULE_NAME6 = "no-direct-set-state-in-use-layout-effect";
|
|
603
734
|
var RULE_FEATURES6 = [
|
|
604
735
|
"EXP"
|
|
605
736
|
];
|
|
606
|
-
var
|
|
607
|
-
"Boolean",
|
|
608
|
-
"String",
|
|
609
|
-
"Number"
|
|
610
|
-
];
|
|
611
|
-
var prefer_use_state_lazy_initialization_default = createRule({
|
|
737
|
+
var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
612
738
|
meta: {
|
|
613
739
|
type: "problem",
|
|
614
740
|
docs: {
|
|
615
|
-
description: "
|
|
741
|
+
description: "Disallow direct calls to the `set` function of `useState` in `useLayoutEffect`.",
|
|
616
742
|
[Symbol.for("rule_features")]: RULE_FEATURES6
|
|
617
743
|
},
|
|
618
744
|
messages: {
|
|
619
|
-
|
|
745
|
+
noDirectSetStateInUseLayoutEffect: "Do not call the 'set' function '{{name}}' of 'useState' directly in 'useLayoutEffect'."
|
|
620
746
|
},
|
|
621
747
|
schema: []
|
|
622
748
|
},
|
|
@@ -625,41 +751,13 @@ var prefer_use_state_lazy_initialization_default = createRule({
|
|
|
625
751
|
defaultOptions: []
|
|
626
752
|
});
|
|
627
753
|
function create6(context) {
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
if (!isUseStateCall(node)) {
|
|
636
|
-
return;
|
|
637
|
-
}
|
|
638
|
-
const [useStateInput] = node.arguments;
|
|
639
|
-
if (useStateInput == null) {
|
|
640
|
-
return;
|
|
641
|
-
}
|
|
642
|
-
for (const expr of AST.getNestedNewExpressions(useStateInput)) {
|
|
643
|
-
if (!("name" in expr.callee)) continue;
|
|
644
|
-
if (ALLOW_LIST.includes(expr.callee.name)) continue;
|
|
645
|
-
if (AST.findParentNode(expr, (n) => ER7.isUseCall(context, n)) != null) continue;
|
|
646
|
-
context.report({
|
|
647
|
-
messageId: "preferUseStateLazyInitialization",
|
|
648
|
-
node: expr
|
|
649
|
-
});
|
|
650
|
-
}
|
|
651
|
-
for (const expr of AST.getNestedCallExpressions(useStateInput)) {
|
|
652
|
-
if (!("name" in expr.callee)) continue;
|
|
653
|
-
if (ER7.isReactHookName(expr.callee.name)) continue;
|
|
654
|
-
if (ALLOW_LIST.includes(expr.callee.name)) continue;
|
|
655
|
-
if (AST.findParentNode(expr, (n) => ER7.isUseCall(context, n)) != null) continue;
|
|
656
|
-
context.report({
|
|
657
|
-
messageId: "preferUseStateLazyInitialization",
|
|
658
|
-
node: expr
|
|
659
|
-
});
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
};
|
|
754
|
+
if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
|
|
755
|
+
return useNoDirectSetStateInUseEffect(context, {
|
|
756
|
+
onViolation(ctx, node, data) {
|
|
757
|
+
ctx.report({ messageId: "noDirectSetStateInUseLayoutEffect", node, data });
|
|
758
|
+
},
|
|
759
|
+
useEffectKind: "useLayoutEffect"
|
|
760
|
+
});
|
|
663
761
|
}
|
|
664
762
|
|
|
665
763
|
// src/plugin.ts
|
|
@@ -671,9 +769,25 @@ var plugin = {
|
|
|
671
769
|
rules: {
|
|
672
770
|
"no-direct-set-state-in-use-effect": no_direct_set_state_in_use_effect_default,
|
|
673
771
|
"no-direct-set-state-in-use-layout-effect": no_direct_set_state_in_use_layout_effect_default,
|
|
772
|
+
/**
|
|
773
|
+
* @deprecated Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead.
|
|
774
|
+
* @see https://next.eslint-react.xyz/docs/rules/no-unnecessary-use-callback
|
|
775
|
+
*/
|
|
674
776
|
"no-unnecessary-use-callback": no_unnecessary_use_callback_default,
|
|
777
|
+
/**
|
|
778
|
+
* @deprecated Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead.
|
|
779
|
+
* @see https://next.eslint-react.xyz/docs/rules/no-unnecessary-use-memo
|
|
780
|
+
*/
|
|
675
781
|
"no-unnecessary-use-memo": no_unnecessary_use_memo_default,
|
|
782
|
+
/**
|
|
783
|
+
* @deprecated Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead.
|
|
784
|
+
* @see https://next.eslint-react.xyz/docs/rules/no-unnecessary-use-prefix
|
|
785
|
+
*/
|
|
676
786
|
"no-unnecessary-use-prefix": no_unnecessary_use_prefix_default,
|
|
787
|
+
/**
|
|
788
|
+
* @deprecated Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead.
|
|
789
|
+
* @see https://next.eslint-react.xyz/docs/rules/prefer-use-state-lazy-initialization
|
|
790
|
+
*/
|
|
677
791
|
"prefer-use-state-lazy-initialization": prefer_use_state_lazy_initialization_default
|
|
678
792
|
}
|
|
679
793
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-hooks-extra",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.44",
|
|
4
4
|
"description": "ESLint React's ESLint plugin for React Hooks related rules.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -36,28 +36,28 @@
|
|
|
36
36
|
"./package.json"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@typescript-eslint/scope-manager": "^8.
|
|
40
|
-
"@typescript-eslint/type-utils": "^8.
|
|
41
|
-
"@typescript-eslint/types": "^8.
|
|
42
|
-
"@typescript-eslint/utils": "^8.
|
|
39
|
+
"@typescript-eslint/scope-manager": "^8.34.0",
|
|
40
|
+
"@typescript-eslint/type-utils": "^8.34.0",
|
|
41
|
+
"@typescript-eslint/types": "^8.34.0",
|
|
42
|
+
"@typescript-eslint/utils": "^8.34.0",
|
|
43
43
|
"string-ts": "^2.2.1",
|
|
44
|
-
"ts-pattern": "^5.7.
|
|
45
|
-
"@eslint-react/
|
|
46
|
-
"@eslint-react/
|
|
47
|
-
"@eslint-react/
|
|
48
|
-
"@eslint-react/
|
|
49
|
-
"@eslint-react/var": "2.0.0-next.
|
|
50
|
-
"@eslint-react/
|
|
44
|
+
"ts-pattern": "^5.7.1",
|
|
45
|
+
"@eslint-react/eff": "2.0.0-next.44",
|
|
46
|
+
"@eslint-react/kit": "2.0.0-next.44",
|
|
47
|
+
"@eslint-react/shared": "2.0.0-next.44",
|
|
48
|
+
"@eslint-react/ast": "2.0.0-next.44",
|
|
49
|
+
"@eslint-react/var": "2.0.0-next.44",
|
|
50
|
+
"@eslint-react/core": "2.0.0-next.44"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@types/react": "^19.1.
|
|
54
|
-
"@types/react-dom": "^19.1.
|
|
55
|
-
"tsup": "^8.
|
|
53
|
+
"@types/react": "^19.1.8",
|
|
54
|
+
"@types/react-dom": "^19.1.6",
|
|
55
|
+
"tsup": "^8.5.0",
|
|
56
56
|
"@local/configs": "0.0.0"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"eslint": "^9.
|
|
60
|
-
"typescript": "^4.9.5 || ^5.
|
|
59
|
+
"eslint": "^8.57.0 || ^9.0.0",
|
|
60
|
+
"typescript": "^4.9.5 || ^5.3.3"
|
|
61
61
|
},
|
|
62
62
|
"peerDependenciesMeta": {
|
|
63
63
|
"eslint": {
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
},
|
|
70
70
|
"engines": {
|
|
71
71
|
"bun": ">=1.0.15",
|
|
72
|
-
"node": ">=
|
|
72
|
+
"node": ">=18.18.0"
|
|
73
73
|
},
|
|
74
74
|
"publishConfig": {
|
|
75
75
|
"access": "public"
|