eslint-plugin-react-x 5.28.2 → 5.28.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 +32 -36
- package/package.json +11 -11
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { P, isMatching, match } from "ts-pattern";
|
|
|
8
8
|
import { isAssignmentTargetEqual, isInitializedFromReact, resolveEnclosingAssignmentTarget, resolveObjectType, resolveOrigin } from "@eslint-react/var";
|
|
9
9
|
import { DefinitionType, ScopeType } from "@typescript-eslint/scope-manager";
|
|
10
10
|
import { findVariable, getStaticValue } from "@typescript-eslint/utils/ast-utils";
|
|
11
|
-
import { findParentAttribute, getElementFullType, hasAttribute } from "@eslint-react/jsx";
|
|
11
|
+
import { findParentAttribute, getElementFullType, hasAttribute, isAttribute } from "@eslint-react/jsx";
|
|
12
12
|
import { compare } from "compare-versions";
|
|
13
13
|
import { unionConstituents } from "ts-api-utils";
|
|
14
14
|
import "typescript";
|
|
@@ -135,7 +135,7 @@ const rules$6 = {
|
|
|
135
135
|
//#endregion
|
|
136
136
|
//#region package.json
|
|
137
137
|
var name$6 = "eslint-plugin-react-x";
|
|
138
|
-
var version = "5.28.
|
|
138
|
+
var version = "5.28.3";
|
|
139
139
|
//#endregion
|
|
140
140
|
//#region src/utils/create-rule.ts
|
|
141
141
|
function getDocsUrl(ruleName) {
|
|
@@ -3232,40 +3232,36 @@ function create$13(context) {
|
|
|
3232
3232
|
if (compilationMode === "annotation" && context.sourceCode.ast.body.some((stmt) => Check.isDirective(stmt, "use memo"))) return {};
|
|
3233
3233
|
const isReact18OrBelow = compare(version, "19.0.0", "<");
|
|
3234
3234
|
const { api, visitor } = core.getFunctionComponentCollector(context);
|
|
3235
|
-
const
|
|
3235
|
+
const valueExpressions = [];
|
|
3236
3236
|
return merge(visitor, {
|
|
3237
3237
|
JSXOpeningElement(node) {
|
|
3238
3238
|
const selfName = getElementFullType(node.parent).split(".").at(-1);
|
|
3239
3239
|
if (selfName == null) return;
|
|
3240
3240
|
if (!isContextName(selfName, isReact18OrBelow)) return;
|
|
3241
|
-
const
|
|
3242
|
-
if (
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
const value = attribute.value;
|
|
3247
|
-
if (value?.type !== AST_NODE_TYPES.JSXExpressionContainer) return;
|
|
3248
|
-
const valueExpression = value.expression;
|
|
3249
|
-
const construction = resolveObjectType(context, valueExpression);
|
|
3250
|
-
if (construction == null) return;
|
|
3251
|
-
if (core.isHookCall(construction.node)) return;
|
|
3252
|
-
getOrInsertComputed(constructions, enclosingFunction, () => []).push(construction);
|
|
3241
|
+
const attribute = node.attributes.findLast(isAttribute("value"));
|
|
3242
|
+
if (attribute?.value?.type !== AST_NODE_TYPES.JSXExpressionContainer) return;
|
|
3243
|
+
const { expression } = attribute.value;
|
|
3244
|
+
if (expression.type === AST_NODE_TYPES.JSXEmptyExpression) return;
|
|
3245
|
+
valueExpressions.push(expression);
|
|
3253
3246
|
},
|
|
3254
3247
|
"Program:exit"(program) {
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3248
|
+
const components = api.getAllComponents(program).filter(({ directives }) => compilationMode !== "annotation" || !directives.some((d) => d.directive === "use memo")).map(({ node }) => node).sort((a, b) => a.range[1] - a.range[0] - (b.range[1] - b.range[0]));
|
|
3249
|
+
for (const valueExpression of valueExpressions) {
|
|
3250
|
+
const component = components.find((node) => node.range[0] <= valueExpression.range[0] && valueExpression.range[1] <= node.range[1]);
|
|
3251
|
+
if (component == null) continue;
|
|
3252
|
+
const construction = resolveObjectType(context, valueExpression, { boundary: component });
|
|
3253
|
+
if (construction == null) continue;
|
|
3254
|
+
if (core.isHookCall(construction.node)) continue;
|
|
3255
|
+
const { kind, node: constructionNode } = construction;
|
|
3256
|
+
const suggestion = kind === "function" ? "Consider wrapping it in a useCallback hook." : "Consider wrapping it in a useMemo hook.";
|
|
3257
|
+
context.report({
|
|
3258
|
+
data: {
|
|
3259
|
+
kind: getHumanReadableKind$1(constructionNode),
|
|
3260
|
+
suggestion
|
|
3261
|
+
},
|
|
3262
|
+
messageId: "unstable-context-value",
|
|
3263
|
+
node: constructionNode
|
|
3264
|
+
});
|
|
3269
3265
|
}
|
|
3270
3266
|
}
|
|
3271
3267
|
});
|
|
@@ -3313,28 +3309,28 @@ function create$12(context, [options]) {
|
|
|
3313
3309
|
if (compilationMode === "infer" || compilationMode === "all") return {};
|
|
3314
3310
|
if (compilationMode === "annotation" && context.sourceCode.ast.body.some((stmt) => Check.isDirective(stmt, "use memo"))) return {};
|
|
3315
3311
|
const { api, visitor } = core.getFunctionComponentCollector(context);
|
|
3316
|
-
const declarators =
|
|
3312
|
+
const declarators = [];
|
|
3317
3313
|
const { safeDefaultProps = [] } = options;
|
|
3318
3314
|
const safePatterns = safeDefaultProps.map((s) => toRegExp(s));
|
|
3319
3315
|
return merge(visitor, {
|
|
3320
3316
|
[SEL_OBJECT_DESTRUCTURING_VARIABLE_DECLARATOR](node) {
|
|
3321
|
-
|
|
3322
|
-
if (enclosingFunction == null) return;
|
|
3323
|
-
getOrInsertComputed(declarators, enclosingFunction, () => []).push(node);
|
|
3317
|
+
declarators.push(node);
|
|
3324
3318
|
},
|
|
3325
3319
|
"Program:exit"(program) {
|
|
3326
|
-
|
|
3320
|
+
const components = api.getAllComponents(program).map(({ node }) => node).sort((a, b) => a.range[1] - a.range[0] - (b.range[1] - b.range[0]));
|
|
3321
|
+
const innermostComponentOf = (node) => components.find((component) => component.range[0] <= node.range[0] && node.range[1] <= component.range[1]);
|
|
3322
|
+
for (const component of components) {
|
|
3327
3323
|
const { params } = component;
|
|
3328
3324
|
const [props] = params;
|
|
3329
3325
|
if (props == null) continue;
|
|
3330
3326
|
const properties = match(props).with({ type: AST_NODE_TYPES.ObjectPattern }, ({ properties }) => properties).with({ type: AST_NODE_TYPES.Identifier }, ({ name }) => {
|
|
3331
|
-
return declarators.
|
|
3327
|
+
return declarators.filter((d) => d.init.name === name && innermostComponentOf(d) === component).flatMap((d) => d.id.properties);
|
|
3332
3328
|
}).otherwise(() => []);
|
|
3333
3329
|
for (const prop of properties) {
|
|
3334
3330
|
if (prop.type !== AST_NODE_TYPES.Property || prop.value.type !== AST_NODE_TYPES.AssignmentPattern) continue;
|
|
3335
3331
|
const { value } = prop;
|
|
3336
3332
|
const { right } = value;
|
|
3337
|
-
const construction = resolveObjectType(context, value);
|
|
3333
|
+
const construction = resolveObjectType(context, value, { boundary: component });
|
|
3338
3334
|
if (construction == null) continue;
|
|
3339
3335
|
if (core.isHookCall(construction.node)) continue;
|
|
3340
3336
|
if (safePatterns.length > 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-x",
|
|
3
|
-
"version": "5.28.
|
|
3
|
+
"version": "5.28.3",
|
|
4
4
|
"description": "A set of composable ESLint rules for libraries and frameworks that use React as a UI runtime.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -36,16 +36,16 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@eslint-react/ast": "5.28.
|
|
40
|
-
"@eslint-react/core": "5.28.
|
|
41
|
-
"@eslint-react/eslint": "5.28.
|
|
42
|
-
"@eslint-react/jsx": "5.28.
|
|
43
|
-
"@eslint-react/shared": "5.28.
|
|
44
|
-
"@eslint-react/var": "5.28.
|
|
45
|
-
"@typescript-eslint/scope-manager": "^8.
|
|
46
|
-
"@typescript-eslint/types": "^8.
|
|
47
|
-
"@typescript-eslint/typescript-estree": "^8.
|
|
48
|
-
"@typescript-eslint/utils": "^8.
|
|
39
|
+
"@eslint-react/ast": "5.28.3",
|
|
40
|
+
"@eslint-react/core": "5.28.3",
|
|
41
|
+
"@eslint-react/eslint": "5.28.3",
|
|
42
|
+
"@eslint-react/jsx": "5.28.3",
|
|
43
|
+
"@eslint-react/shared": "5.28.3",
|
|
44
|
+
"@eslint-react/var": "5.28.3",
|
|
45
|
+
"@typescript-eslint/scope-manager": "^8.72.0",
|
|
46
|
+
"@typescript-eslint/types": "^8.72.0",
|
|
47
|
+
"@typescript-eslint/typescript-estree": "^8.72.0",
|
|
48
|
+
"@typescript-eslint/utils": "^8.72.0",
|
|
49
49
|
"compare-versions": "^6.1.1",
|
|
50
50
|
"string-ts": "^2.3.1",
|
|
51
51
|
"ts-api-utils": "^2.5.0",
|