eslint-plugin-react-hooks-extra 1.5.26-beta.1 → 1.5.26-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +64 -18
- package/dist/index.mjs +65 -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.2";
|
|
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,32 @@ 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).references),
|
|
282
|
+
tools.O.exists((refs) => refs.some((x2) => x2.resolved?.scope.block === component))
|
|
265
283
|
);
|
|
266
|
-
|
|
284
|
+
if (isReferencedToComponentScope) return;
|
|
285
|
+
context.report({
|
|
286
|
+
messageId: "ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS",
|
|
287
|
+
node
|
|
288
|
+
});
|
|
267
289
|
}
|
|
268
290
|
};
|
|
269
291
|
},
|
|
@@ -277,7 +299,7 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
277
299
|
description: "enforce 'useMemo' has non-empty dependencies array"
|
|
278
300
|
},
|
|
279
301
|
messages: {
|
|
280
|
-
ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS: "An useMemo should have a non-empty dependencies array."
|
|
302
|
+
ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS: "An 'useMemo' should have a non-empty dependencies array."
|
|
281
303
|
},
|
|
282
304
|
schema: []
|
|
283
305
|
},
|
|
@@ -286,10 +308,15 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
286
308
|
const alias = shared.getESLintReactSettings(context.settings).additionalHooks?.useMemo ?? [];
|
|
287
309
|
return {
|
|
288
310
|
CallExpression(node) {
|
|
289
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
290
311
|
if (!core.isReactHookCall(node)) return;
|
|
291
|
-
|
|
292
|
-
|
|
312
|
+
const initialScope = context.sourceCode.getScope(node);
|
|
313
|
+
if (!core.isUseMemoCall(node, context) && !alias.some(tools.F.flip(core.isReactHookCallWithNameLoose)(node))) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const scope = context.sourceCode.getScope(node);
|
|
317
|
+
const component = scope.block;
|
|
318
|
+
if (!ast.isFunction(component)) return;
|
|
319
|
+
const [cb, deps] = node.arguments;
|
|
293
320
|
if (!deps) {
|
|
294
321
|
context.report({
|
|
295
322
|
messageId: "ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS",
|
|
@@ -297,7 +324,7 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
297
324
|
});
|
|
298
325
|
return;
|
|
299
326
|
}
|
|
300
|
-
const
|
|
327
|
+
const hasEmptyDeps = tools.F.pipe(
|
|
301
328
|
$(deps).with({ type: ast.NodeType.ArrayExpression }, tools.O.some).with({ type: ast.NodeType.Identifier }, (n2) => {
|
|
302
329
|
return tools.F.pipe(
|
|
303
330
|
_var.findVariable(n2.name, initialScope),
|
|
@@ -305,13 +332,32 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
305
332
|
tools.O.filter(ast.is(ast.NodeType.ArrayExpression))
|
|
306
333
|
);
|
|
307
334
|
}).otherwise(tools.O.none),
|
|
308
|
-
tools.O.
|
|
309
|
-
|
|
335
|
+
tools.O.exists((x2) => x2.elements.length === 0)
|
|
336
|
+
);
|
|
337
|
+
if (!hasEmptyDeps) return;
|
|
338
|
+
if (!cb) {
|
|
339
|
+
context.report({
|
|
310
340
|
messageId: "ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS",
|
|
311
341
|
node
|
|
312
|
-
})
|
|
342
|
+
});
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
const isReferencedToComponentScope = tools.F.pipe(
|
|
346
|
+
$(cb).with({ type: ast.NodeType.ArrowFunctionExpression }, tools.O.some).with({ type: ast.NodeType.FunctionExpression }, tools.O.some).with({ type: ast.NodeType.Identifier }, (n2) => {
|
|
347
|
+
return tools.F.pipe(
|
|
348
|
+
_var.findVariable(n2.name, initialScope),
|
|
349
|
+
tools.O.flatMap(_var.getVariableInit(0)),
|
|
350
|
+
tools.O.filter(ast.isFunction)
|
|
351
|
+
);
|
|
352
|
+
}).otherwise(tools.O.none),
|
|
353
|
+
tools.O.map((n2) => context.sourceCode.getScope(n2).references),
|
|
354
|
+
tools.O.exists((refs) => refs.some((x2) => x2.resolved?.scope.block === component))
|
|
313
355
|
);
|
|
314
|
-
|
|
356
|
+
if (isReferencedToComponentScope) return;
|
|
357
|
+
context.report({
|
|
358
|
+
messageId: "ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS",
|
|
359
|
+
node
|
|
360
|
+
});
|
|
315
361
|
}
|
|
316
362
|
};
|
|
317
363
|
},
|
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.2";
|
|
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,32 @@ 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).references),
|
|
280
|
+
O.exists((refs) => refs.some((x2) => x2.resolved?.scope.block === component))
|
|
263
281
|
);
|
|
264
|
-
|
|
282
|
+
if (isReferencedToComponentScope) return;
|
|
283
|
+
context.report({
|
|
284
|
+
messageId: "ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS",
|
|
285
|
+
node
|
|
286
|
+
});
|
|
265
287
|
}
|
|
266
288
|
};
|
|
267
289
|
},
|
|
@@ -275,7 +297,7 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
275
297
|
description: "enforce 'useMemo' has non-empty dependencies array"
|
|
276
298
|
},
|
|
277
299
|
messages: {
|
|
278
|
-
ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS: "An useMemo should have a non-empty dependencies array."
|
|
300
|
+
ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS: "An 'useMemo' should have a non-empty dependencies array."
|
|
279
301
|
},
|
|
280
302
|
schema: []
|
|
281
303
|
},
|
|
@@ -284,10 +306,15 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
284
306
|
const alias = getESLintReactSettings(context.settings).additionalHooks?.useMemo ?? [];
|
|
285
307
|
return {
|
|
286
308
|
CallExpression(node) {
|
|
287
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
288
309
|
if (!isReactHookCall(node)) return;
|
|
289
|
-
|
|
290
|
-
|
|
310
|
+
const initialScope = context.sourceCode.getScope(node);
|
|
311
|
+
if (!isUseMemoCall(node, context) && !alias.some(F.flip(isReactHookCallWithNameLoose)(node))) {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
const scope = context.sourceCode.getScope(node);
|
|
315
|
+
const component = scope.block;
|
|
316
|
+
if (!isFunction(component)) return;
|
|
317
|
+
const [cb, deps] = node.arguments;
|
|
291
318
|
if (!deps) {
|
|
292
319
|
context.report({
|
|
293
320
|
messageId: "ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS",
|
|
@@ -295,7 +322,7 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
295
322
|
});
|
|
296
323
|
return;
|
|
297
324
|
}
|
|
298
|
-
const
|
|
325
|
+
const hasEmptyDeps = F.pipe(
|
|
299
326
|
$(deps).with({ type: NodeType.ArrayExpression }, O.some).with({ type: NodeType.Identifier }, (n2) => {
|
|
300
327
|
return F.pipe(
|
|
301
328
|
findVariable(n2.name, initialScope),
|
|
@@ -303,13 +330,32 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
|
|
|
303
330
|
O.filter(is(NodeType.ArrayExpression))
|
|
304
331
|
);
|
|
305
332
|
}).otherwise(O.none),
|
|
306
|
-
O.
|
|
307
|
-
|
|
333
|
+
O.exists((x2) => x2.elements.length === 0)
|
|
334
|
+
);
|
|
335
|
+
if (!hasEmptyDeps) return;
|
|
336
|
+
if (!cb) {
|
|
337
|
+
context.report({
|
|
308
338
|
messageId: "ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS",
|
|
309
339
|
node
|
|
310
|
-
})
|
|
340
|
+
});
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
const isReferencedToComponentScope = F.pipe(
|
|
344
|
+
$(cb).with({ type: NodeType.ArrowFunctionExpression }, O.some).with({ type: NodeType.FunctionExpression }, O.some).with({ type: NodeType.Identifier }, (n2) => {
|
|
345
|
+
return F.pipe(
|
|
346
|
+
findVariable(n2.name, initialScope),
|
|
347
|
+
O.flatMap(getVariableInit(0)),
|
|
348
|
+
O.filter(isFunction)
|
|
349
|
+
);
|
|
350
|
+
}).otherwise(O.none),
|
|
351
|
+
O.map((n2) => context.sourceCode.getScope(n2).references),
|
|
352
|
+
O.exists((refs) => refs.some((x2) => x2.resolved?.scope.block === component))
|
|
311
353
|
);
|
|
312
|
-
|
|
354
|
+
if (isReferencedToComponentScope) return;
|
|
355
|
+
context.report({
|
|
356
|
+
messageId: "ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS",
|
|
357
|
+
node
|
|
358
|
+
});
|
|
313
359
|
}
|
|
314
360
|
};
|
|
315
361
|
},
|
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.2",
|
|
4
4
|
"description": "ESLint React's ESLint plugin for React Hooks related rules.",
|
|
5
5
|
"homepage": "https://github.com/rel1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -39,13 +39,13 @@
|
|
|
39
39
|
"@typescript-eslint/type-utils": "^7.16.0",
|
|
40
40
|
"@typescript-eslint/types": "^7.16.0",
|
|
41
41
|
"@typescript-eslint/utils": "^7.16.0",
|
|
42
|
-
"@eslint-react/ast": "1.5.26-beta.
|
|
43
|
-
"@eslint-react/
|
|
44
|
-
"@eslint-react/
|
|
45
|
-
"@eslint-react/
|
|
46
|
-
"@eslint-react/
|
|
47
|
-
"@eslint-react/
|
|
48
|
-
"@eslint-react/
|
|
42
|
+
"@eslint-react/ast": "1.5.26-beta.2",
|
|
43
|
+
"@eslint-react/jsx": "1.5.26-beta.2",
|
|
44
|
+
"@eslint-react/core": "1.5.26-beta.2",
|
|
45
|
+
"@eslint-react/shared": "1.5.26-beta.2",
|
|
46
|
+
"@eslint-react/tools": "1.5.26-beta.2",
|
|
47
|
+
"@eslint-react/types": "1.5.26-beta.2",
|
|
48
|
+
"@eslint-react/var": "1.5.26-beta.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"string-ts": "2.2.0",
|