eslint-plugin-react-hooks-extra 1.5.26-beta.1 → 1.5.26-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +66 -18
- package/dist/index.mjs +67 -19
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ 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.5.26-beta.
|
|
12
|
+
var version = "1.5.26-beta.3";
|
|
13
13
|
var createRule = shared.createRuleForPlugin("hooks-extra");
|
|
14
14
|
|
|
15
15
|
// src/rules/ensure-custom-hooks-using-other-hooks.ts
|
|
@@ -227,7 +227,7 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
227
227
|
description: "enforce 'useCallback' has non-empty dependencies array"
|
|
228
228
|
},
|
|
229
229
|
messages: {
|
|
230
|
-
ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS: "An useCallback should have a non-empty dependencies array."
|
|
230
|
+
ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS: "An 'useCallback' should have a non-empty dependencies array."
|
|
231
231
|
},
|
|
232
232
|
schema: []
|
|
233
233
|
},
|
|
@@ -236,12 +236,15 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
236
236
|
const alias = shared.getESLintReactSettings(context.settings).additionalHooks?.useCallback ?? [];
|
|
237
237
|
return {
|
|
238
238
|
CallExpression(node) {
|
|
239
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
240
239
|
if (!core.isReactHookCall(node)) return;
|
|
240
|
+
const initialScope = context.sourceCode.getScope(node);
|
|
241
241
|
if (!core.isUseCallbackCall(node, context) && !alias.some(tools.F.flip(core.isReactHookCallWithNameLoose)(node))) {
|
|
242
242
|
return;
|
|
243
243
|
}
|
|
244
|
-
const
|
|
244
|
+
const scope = context.sourceCode.getScope(node);
|
|
245
|
+
const component = scope.block;
|
|
246
|
+
if (!ast.isFunction(component)) return;
|
|
247
|
+
const [cb, deps] = node.arguments;
|
|
245
248
|
if (!deps) {
|
|
246
249
|
context.report({
|
|
247
250
|
messageId: "ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS",
|
|
@@ -249,7 +252,7 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
249
252
|
});
|
|
250
253
|
return;
|
|
251
254
|
}
|
|
252
|
-
const
|
|
255
|
+
const hasEmptyDeps = tools.F.pipe(
|
|
253
256
|
$(deps).with({ type: ast.NodeType.ArrayExpression }, tools.O.some).with({ type: ast.NodeType.Identifier }, (n2) => {
|
|
254
257
|
return tools.F.pipe(
|
|
255
258
|
_var.findVariable(n2.name, initialScope),
|
|
@@ -257,13 +260,33 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
257
260
|
tools.O.filter(ast.is(ast.NodeType.ArrayExpression))
|
|
258
261
|
);
|
|
259
262
|
}).otherwise(tools.O.none),
|
|
260
|
-
tools.O.
|
|
261
|
-
|
|
263
|
+
tools.O.exists((x2) => x2.elements.length === 0)
|
|
264
|
+
);
|
|
265
|
+
if (!hasEmptyDeps) return;
|
|
266
|
+
if (!cb) {
|
|
267
|
+
context.report({
|
|
262
268
|
messageId: "ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS",
|
|
263
269
|
node
|
|
264
|
-
})
|
|
270
|
+
});
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
const isReferencedToComponentScope = tools.F.pipe(
|
|
274
|
+
$(cb).with({ type: ast.NodeType.ArrowFunctionExpression }, tools.O.some).with({ type: ast.NodeType.FunctionExpression }, tools.O.some).with({ type: ast.NodeType.Identifier }, (n2) => {
|
|
275
|
+
return tools.F.pipe(
|
|
276
|
+
_var.findVariable(n2.name, initialScope),
|
|
277
|
+
tools.O.flatMap(_var.getVariableInit(0)),
|
|
278
|
+
tools.O.filter(ast.isFunction)
|
|
279
|
+
);
|
|
280
|
+
}).otherwise(tools.O.none),
|
|
281
|
+
tools.O.map((n2) => context.sourceCode.getScope(n2)),
|
|
282
|
+
tools.O.map((s2) => [...s2.childScopes, s2].flatMap((x2) => x2.references)),
|
|
283
|
+
tools.O.exists((refs) => refs.some((x2) => x2.resolved?.scope.block === component))
|
|
265
284
|
);
|
|
266
|
-
|
|
285
|
+
if (isReferencedToComponentScope) return;
|
|
286
|
+
context.report({
|
|
287
|
+
messageId: "ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS",
|
|
288
|
+
node
|
|
289
|
+
});
|
|
267
290
|
}
|
|
268
291
|
};
|
|
269
292
|
},
|
|
@@ -277,7 +300,7 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
277
300
|
description: "enforce 'useMemo' has non-empty dependencies array"
|
|
278
301
|
},
|
|
279
302
|
messages: {
|
|
280
|
-
ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS: "An useMemo should have a non-empty dependencies array."
|
|
303
|
+
ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS: "An 'useMemo' should have a non-empty dependencies array."
|
|
281
304
|
},
|
|
282
305
|
schema: []
|
|
283
306
|
},
|
|
@@ -286,10 +309,15 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
286
309
|
const alias = shared.getESLintReactSettings(context.settings).additionalHooks?.useMemo ?? [];
|
|
287
310
|
return {
|
|
288
311
|
CallExpression(node) {
|
|
289
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
290
312
|
if (!core.isReactHookCall(node)) return;
|
|
291
|
-
|
|
292
|
-
|
|
313
|
+
const initialScope = context.sourceCode.getScope(node);
|
|
314
|
+
if (!core.isUseMemoCall(node, context) && !alias.some(tools.F.flip(core.isReactHookCallWithNameLoose)(node))) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const scope = context.sourceCode.getScope(node);
|
|
318
|
+
const component = scope.block;
|
|
319
|
+
if (!ast.isFunction(component)) return;
|
|
320
|
+
const [cb, deps] = node.arguments;
|
|
293
321
|
if (!deps) {
|
|
294
322
|
context.report({
|
|
295
323
|
messageId: "ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS",
|
|
@@ -297,7 +325,7 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
297
325
|
});
|
|
298
326
|
return;
|
|
299
327
|
}
|
|
300
|
-
const
|
|
328
|
+
const hasEmptyDeps = tools.F.pipe(
|
|
301
329
|
$(deps).with({ type: ast.NodeType.ArrayExpression }, tools.O.some).with({ type: ast.NodeType.Identifier }, (n2) => {
|
|
302
330
|
return tools.F.pipe(
|
|
303
331
|
_var.findVariable(n2.name, initialScope),
|
|
@@ -305,13 +333,33 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
305
333
|
tools.O.filter(ast.is(ast.NodeType.ArrayExpression))
|
|
306
334
|
);
|
|
307
335
|
}).otherwise(tools.O.none),
|
|
308
|
-
tools.O.
|
|
309
|
-
|
|
336
|
+
tools.O.exists((x2) => x2.elements.length === 0)
|
|
337
|
+
);
|
|
338
|
+
if (!hasEmptyDeps) return;
|
|
339
|
+
if (!cb) {
|
|
340
|
+
context.report({
|
|
310
341
|
messageId: "ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS",
|
|
311
342
|
node
|
|
312
|
-
})
|
|
343
|
+
});
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const isReferencedToComponentScope = tools.F.pipe(
|
|
347
|
+
$(cb).with({ type: ast.NodeType.ArrowFunctionExpression }, tools.O.some).with({ type: ast.NodeType.FunctionExpression }, tools.O.some).with({ type: ast.NodeType.Identifier }, (n2) => {
|
|
348
|
+
return tools.F.pipe(
|
|
349
|
+
_var.findVariable(n2.name, initialScope),
|
|
350
|
+
tools.O.flatMap(_var.getVariableInit(0)),
|
|
351
|
+
tools.O.filter(ast.isFunction)
|
|
352
|
+
);
|
|
353
|
+
}).otherwise(tools.O.none),
|
|
354
|
+
tools.O.map((n2) => context.sourceCode.getScope(n2)),
|
|
355
|
+
tools.O.map((s2) => [...s2.childScopes, s2].flatMap((x2) => x2.references)),
|
|
356
|
+
tools.O.exists((refs) => refs.some((x2) => x2.resolved?.scope.block === component))
|
|
313
357
|
);
|
|
314
|
-
|
|
358
|
+
if (isReferencedToComponentScope) return;
|
|
359
|
+
context.report({
|
|
360
|
+
messageId: "ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS",
|
|
361
|
+
node
|
|
362
|
+
});
|
|
315
363
|
}
|
|
316
364
|
};
|
|
317
365
|
},
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { useHookCollector, isReactHookCall, isUseCallbackCall, isReactHookCallWithNameLoose, isUseMemoCall, isUseStateCall, isUseEffectCall, isUseLayoutEffectCall } from '@eslint-react/core';
|
|
2
2
|
import { createRuleForPlugin, getESLintReactSettings } from '@eslint-react/shared';
|
|
3
|
-
import { NodeType, is, traverseUp, getNestedCallExpressions } from '@eslint-react/ast';
|
|
3
|
+
import { isFunction, NodeType, is, traverseUp, getNestedCallExpressions } from '@eslint-react/ast';
|
|
4
4
|
import { F, O } from '@eslint-react/tools';
|
|
5
5
|
import { findVariable, getVariableInit } from '@eslint-react/var';
|
|
6
6
|
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.5.26-beta.
|
|
10
|
+
var version = "1.5.26-beta.3";
|
|
11
11
|
var createRule = createRuleForPlugin("hooks-extra");
|
|
12
12
|
|
|
13
13
|
// src/rules/ensure-custom-hooks-using-other-hooks.ts
|
|
@@ -225,7 +225,7 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
225
225
|
description: "enforce 'useCallback' has non-empty dependencies array"
|
|
226
226
|
},
|
|
227
227
|
messages: {
|
|
228
|
-
ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS: "An useCallback should have a non-empty dependencies array."
|
|
228
|
+
ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS: "An 'useCallback' should have a non-empty dependencies array."
|
|
229
229
|
},
|
|
230
230
|
schema: []
|
|
231
231
|
},
|
|
@@ -234,12 +234,15 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
234
234
|
const alias = getESLintReactSettings(context.settings).additionalHooks?.useCallback ?? [];
|
|
235
235
|
return {
|
|
236
236
|
CallExpression(node) {
|
|
237
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
238
237
|
if (!isReactHookCall(node)) return;
|
|
238
|
+
const initialScope = context.sourceCode.getScope(node);
|
|
239
239
|
if (!isUseCallbackCall(node, context) && !alias.some(F.flip(isReactHookCallWithNameLoose)(node))) {
|
|
240
240
|
return;
|
|
241
241
|
}
|
|
242
|
-
const
|
|
242
|
+
const scope = context.sourceCode.getScope(node);
|
|
243
|
+
const component = scope.block;
|
|
244
|
+
if (!isFunction(component)) return;
|
|
245
|
+
const [cb, deps] = node.arguments;
|
|
243
246
|
if (!deps) {
|
|
244
247
|
context.report({
|
|
245
248
|
messageId: "ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS",
|
|
@@ -247,7 +250,7 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
247
250
|
});
|
|
248
251
|
return;
|
|
249
252
|
}
|
|
250
|
-
const
|
|
253
|
+
const hasEmptyDeps = F.pipe(
|
|
251
254
|
$(deps).with({ type: NodeType.ArrayExpression }, O.some).with({ type: NodeType.Identifier }, (n2) => {
|
|
252
255
|
return F.pipe(
|
|
253
256
|
findVariable(n2.name, initialScope),
|
|
@@ -255,13 +258,33 @@ var ensure_use_callback_has_non_empty_deps_default = createRule({
|
|
|
255
258
|
O.filter(is(NodeType.ArrayExpression))
|
|
256
259
|
);
|
|
257
260
|
}).otherwise(O.none),
|
|
258
|
-
O.
|
|
259
|
-
|
|
261
|
+
O.exists((x2) => x2.elements.length === 0)
|
|
262
|
+
);
|
|
263
|
+
if (!hasEmptyDeps) return;
|
|
264
|
+
if (!cb) {
|
|
265
|
+
context.report({
|
|
260
266
|
messageId: "ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS",
|
|
261
267
|
node
|
|
262
|
-
})
|
|
268
|
+
});
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const isReferencedToComponentScope = F.pipe(
|
|
272
|
+
$(cb).with({ type: NodeType.ArrowFunctionExpression }, O.some).with({ type: NodeType.FunctionExpression }, O.some).with({ type: NodeType.Identifier }, (n2) => {
|
|
273
|
+
return F.pipe(
|
|
274
|
+
findVariable(n2.name, initialScope),
|
|
275
|
+
O.flatMap(getVariableInit(0)),
|
|
276
|
+
O.filter(isFunction)
|
|
277
|
+
);
|
|
278
|
+
}).otherwise(O.none),
|
|
279
|
+
O.map((n2) => context.sourceCode.getScope(n2)),
|
|
280
|
+
O.map((s2) => [...s2.childScopes, s2].flatMap((x2) => x2.references)),
|
|
281
|
+
O.exists((refs) => refs.some((x2) => x2.resolved?.scope.block === component))
|
|
263
282
|
);
|
|
264
|
-
|
|
283
|
+
if (isReferencedToComponentScope) return;
|
|
284
|
+
context.report({
|
|
285
|
+
messageId: "ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS",
|
|
286
|
+
node
|
|
287
|
+
});
|
|
265
288
|
}
|
|
266
289
|
};
|
|
267
290
|
},
|
|
@@ -275,7 +298,7 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
275
298
|
description: "enforce 'useMemo' has non-empty dependencies array"
|
|
276
299
|
},
|
|
277
300
|
messages: {
|
|
278
|
-
ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS: "An useMemo should have a non-empty dependencies array."
|
|
301
|
+
ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS: "An 'useMemo' should have a non-empty dependencies array."
|
|
279
302
|
},
|
|
280
303
|
schema: []
|
|
281
304
|
},
|
|
@@ -284,10 +307,15 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
284
307
|
const alias = getESLintReactSettings(context.settings).additionalHooks?.useMemo ?? [];
|
|
285
308
|
return {
|
|
286
309
|
CallExpression(node) {
|
|
287
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
288
310
|
if (!isReactHookCall(node)) return;
|
|
289
|
-
|
|
290
|
-
|
|
311
|
+
const initialScope = context.sourceCode.getScope(node);
|
|
312
|
+
if (!isUseMemoCall(node, context) && !alias.some(F.flip(isReactHookCallWithNameLoose)(node))) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
const scope = context.sourceCode.getScope(node);
|
|
316
|
+
const component = scope.block;
|
|
317
|
+
if (!isFunction(component)) return;
|
|
318
|
+
const [cb, deps] = node.arguments;
|
|
291
319
|
if (!deps) {
|
|
292
320
|
context.report({
|
|
293
321
|
messageId: "ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS",
|
|
@@ -295,7 +323,7 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
295
323
|
});
|
|
296
324
|
return;
|
|
297
325
|
}
|
|
298
|
-
const
|
|
326
|
+
const hasEmptyDeps = F.pipe(
|
|
299
327
|
$(deps).with({ type: NodeType.ArrayExpression }, O.some).with({ type: NodeType.Identifier }, (n2) => {
|
|
300
328
|
return F.pipe(
|
|
301
329
|
findVariable(n2.name, initialScope),
|
|
@@ -303,13 +331,33 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
303
331
|
O.filter(is(NodeType.ArrayExpression))
|
|
304
332
|
);
|
|
305
333
|
}).otherwise(O.none),
|
|
306
|
-
O.
|
|
307
|
-
|
|
334
|
+
O.exists((x2) => x2.elements.length === 0)
|
|
335
|
+
);
|
|
336
|
+
if (!hasEmptyDeps) return;
|
|
337
|
+
if (!cb) {
|
|
338
|
+
context.report({
|
|
308
339
|
messageId: "ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS",
|
|
309
340
|
node
|
|
310
|
-
})
|
|
341
|
+
});
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
const isReferencedToComponentScope = F.pipe(
|
|
345
|
+
$(cb).with({ type: NodeType.ArrowFunctionExpression }, O.some).with({ type: NodeType.FunctionExpression }, O.some).with({ type: NodeType.Identifier }, (n2) => {
|
|
346
|
+
return F.pipe(
|
|
347
|
+
findVariable(n2.name, initialScope),
|
|
348
|
+
O.flatMap(getVariableInit(0)),
|
|
349
|
+
O.filter(isFunction)
|
|
350
|
+
);
|
|
351
|
+
}).otherwise(O.none),
|
|
352
|
+
O.map((n2) => context.sourceCode.getScope(n2)),
|
|
353
|
+
O.map((s2) => [...s2.childScopes, s2].flatMap((x2) => x2.references)),
|
|
354
|
+
O.exists((refs) => refs.some((x2) => x2.resolved?.scope.block === component))
|
|
311
355
|
);
|
|
312
|
-
|
|
356
|
+
if (isReferencedToComponentScope) return;
|
|
357
|
+
context.report({
|
|
358
|
+
messageId: "ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS",
|
|
359
|
+
node
|
|
360
|
+
});
|
|
313
361
|
}
|
|
314
362
|
};
|
|
315
363
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-hooks-extra",
|
|
3
|
-
"version": "1.5.26-beta.
|
|
3
|
+
"version": "1.5.26-beta.3",
|
|
4
4
|
"description": "ESLint React's ESLint plugin for React Hooks related rules.",
|
|
5
5
|
"homepage": "https://github.com/rel1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -39,13 +39,13 @@
|
|
|
39
39
|
"@typescript-eslint/type-utils": "^7.16.0",
|
|
40
40
|
"@typescript-eslint/types": "^7.16.0",
|
|
41
41
|
"@typescript-eslint/utils": "^7.16.0",
|
|
42
|
-
"@eslint-react/
|
|
43
|
-
"@eslint-react/
|
|
44
|
-
"@eslint-react/
|
|
45
|
-
"@eslint-react/
|
|
46
|
-
"@eslint-react/
|
|
47
|
-
"@eslint-react/
|
|
48
|
-
"@eslint-react/
|
|
42
|
+
"@eslint-react/core": "1.5.26-beta.3",
|
|
43
|
+
"@eslint-react/jsx": "1.5.26-beta.3",
|
|
44
|
+
"@eslint-react/tools": "1.5.26-beta.3",
|
|
45
|
+
"@eslint-react/ast": "1.5.26-beta.3",
|
|
46
|
+
"@eslint-react/types": "1.5.26-beta.3",
|
|
47
|
+
"@eslint-react/shared": "1.5.26-beta.3",
|
|
48
|
+
"@eslint-react/var": "1.5.26-beta.3"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"string-ts": "2.2.0",
|