eslint-plugin-react-x 5.5.2-next.0 → 5.5.3-next.0
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 +97 -48
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -142,7 +142,7 @@ const rules$6 = {
|
|
|
142
142
|
//#endregion
|
|
143
143
|
//#region package.json
|
|
144
144
|
var name$6 = "eslint-plugin-react-x";
|
|
145
|
-
var version = "5.5.
|
|
145
|
+
var version = "5.5.3-next.0";
|
|
146
146
|
|
|
147
147
|
//#endregion
|
|
148
148
|
//#region src/utils/create-rule.ts
|
|
@@ -6932,6 +6932,83 @@ function create$4(context) {
|
|
|
6932
6932
|
});
|
|
6933
6933
|
}
|
|
6934
6934
|
|
|
6935
|
+
//#endregion
|
|
6936
|
+
//#region src/rules/static-components/lib.ts
|
|
6937
|
+
function resolveDynamicValue(context, node, isInsideRender, seen) {
|
|
6938
|
+
const expr = Extract.unwrap(node);
|
|
6939
|
+
switch (expr.type) {
|
|
6940
|
+
case AST_NODE_TYPES.FunctionExpression:
|
|
6941
|
+
case AST_NODE_TYPES.ArrowFunctionExpression:
|
|
6942
|
+
case AST_NODE_TYPES.NewExpression:
|
|
6943
|
+
case AST_NODE_TYPES.CallExpression:
|
|
6944
|
+
case AST_NODE_TYPES.ClassExpression: return expr;
|
|
6945
|
+
case AST_NODE_TYPES.ConditionalExpression: {
|
|
6946
|
+
const consequent = resolveDynamicValue(context, expr.consequent, isInsideRender, seen);
|
|
6947
|
+
if (consequent != null) return consequent;
|
|
6948
|
+
return resolveDynamicValue(context, expr.alternate, isInsideRender, seen);
|
|
6949
|
+
}
|
|
6950
|
+
case AST_NODE_TYPES.Identifier:
|
|
6951
|
+
case AST_NODE_TYPES.JSXIdentifier: {
|
|
6952
|
+
const resolved = findVariableForIdentifier(context, expr);
|
|
6953
|
+
if (resolved == null) return null;
|
|
6954
|
+
return getDynamicComponentSource(context, resolved, isInsideRender, seen).creationNode;
|
|
6955
|
+
}
|
|
6956
|
+
default: return null;
|
|
6957
|
+
}
|
|
6958
|
+
}
|
|
6959
|
+
function findVariableForIdentifier(context, identifier) {
|
|
6960
|
+
let scope = context.sourceCode.getScope(identifier);
|
|
6961
|
+
while (scope != null) {
|
|
6962
|
+
const variable = scope.variables.find((v) => v.name === identifier.name);
|
|
6963
|
+
if (variable != null) return variable;
|
|
6964
|
+
scope = scope.upper;
|
|
6965
|
+
}
|
|
6966
|
+
return null;
|
|
6967
|
+
}
|
|
6968
|
+
function getDynamicComponentSource(context, variable, isInsideRender, seen = /* @__PURE__ */ new Set()) {
|
|
6969
|
+
if (seen.has(variable)) return {
|
|
6970
|
+
isDynamic: false,
|
|
6971
|
+
creationNode: null
|
|
6972
|
+
};
|
|
6973
|
+
seen.add(variable);
|
|
6974
|
+
for (const def of variable.defs) {
|
|
6975
|
+
const defNode = def.node;
|
|
6976
|
+
if (!isInsideRender(defNode)) continue;
|
|
6977
|
+
if (defNode.type === AST_NODE_TYPES.FunctionDeclaration) return {
|
|
6978
|
+
isDynamic: true,
|
|
6979
|
+
creationNode: defNode
|
|
6980
|
+
};
|
|
6981
|
+
if (defNode.type === AST_NODE_TYPES.ClassDeclaration) return {
|
|
6982
|
+
isDynamic: true,
|
|
6983
|
+
creationNode: defNode
|
|
6984
|
+
};
|
|
6985
|
+
if (defNode.type === AST_NODE_TYPES.VariableDeclarator) {
|
|
6986
|
+
if (defNode.init != null) {
|
|
6987
|
+
const source = resolveDynamicValue(context, defNode.init, isInsideRender, seen);
|
|
6988
|
+
if (source != null) return {
|
|
6989
|
+
isDynamic: true,
|
|
6990
|
+
creationNode: source
|
|
6991
|
+
};
|
|
6992
|
+
}
|
|
6993
|
+
for (const ref of variable.references) {
|
|
6994
|
+
if (!ref.isWrite()) continue;
|
|
6995
|
+
const id = ref.identifier;
|
|
6996
|
+
if (id.parent?.type === AST_NODE_TYPES.AssignmentExpression && id.parent.left === id) {
|
|
6997
|
+
const source = resolveDynamicValue(context, id.parent.right, isInsideRender, seen);
|
|
6998
|
+
if (source != null) return {
|
|
6999
|
+
isDynamic: true,
|
|
7000
|
+
creationNode: source
|
|
7001
|
+
};
|
|
7002
|
+
}
|
|
7003
|
+
}
|
|
7004
|
+
}
|
|
7005
|
+
}
|
|
7006
|
+
return {
|
|
7007
|
+
isDynamic: false,
|
|
7008
|
+
creationNode: null
|
|
7009
|
+
};
|
|
7010
|
+
}
|
|
7011
|
+
|
|
6935
7012
|
//#endregion
|
|
6936
7013
|
//#region src/rules/static-components/static-components.ts
|
|
6937
7014
|
const RULE_NAME$3 = "static-components";
|
|
@@ -6939,51 +7016,16 @@ var static_components_default = createRule({
|
|
|
6939
7016
|
meta: {
|
|
6940
7017
|
type: "problem",
|
|
6941
7018
|
docs: { description: "Validates that components are static, not recreated every render." },
|
|
6942
|
-
messages: {
|
|
7019
|
+
messages: {
|
|
7020
|
+
default: "Cannot create components during render. Components created during render will reset their state each time they are created. Declare components outside of render.",
|
|
7021
|
+
createdHere: "The component is created during render here."
|
|
7022
|
+
},
|
|
6943
7023
|
schema: []
|
|
6944
7024
|
},
|
|
6945
7025
|
name: RULE_NAME$3,
|
|
6946
7026
|
create: create$3,
|
|
6947
7027
|
defaultOptions: []
|
|
6948
7028
|
});
|
|
6949
|
-
function findVariableForJSXIdentifier(context, jsxId) {
|
|
6950
|
-
let scope = context.sourceCode.getScope(jsxId);
|
|
6951
|
-
while (scope != null) {
|
|
6952
|
-
const variable = scope.variables.find((v) => v.name === jsxId.name);
|
|
6953
|
-
if (variable != null) return variable;
|
|
6954
|
-
scope = scope.upper;
|
|
6955
|
-
}
|
|
6956
|
-
return null;
|
|
6957
|
-
}
|
|
6958
|
-
function isDynamicallyCreatedValue(node) {
|
|
6959
|
-
const expr = Extract.unwrap(node);
|
|
6960
|
-
switch (expr.type) {
|
|
6961
|
-
case AST_NODE_TYPES.FunctionExpression:
|
|
6962
|
-
case AST_NODE_TYPES.ArrowFunctionExpression:
|
|
6963
|
-
case AST_NODE_TYPES.NewExpression:
|
|
6964
|
-
case AST_NODE_TYPES.CallExpression:
|
|
6965
|
-
case AST_NODE_TYPES.ClassExpression: return true;
|
|
6966
|
-
case AST_NODE_TYPES.ConditionalExpression: return isDynamicallyCreatedValue(expr.consequent) || isDynamicallyCreatedValue(expr.alternate);
|
|
6967
|
-
default: return false;
|
|
6968
|
-
}
|
|
6969
|
-
}
|
|
6970
|
-
function hasDynamicAssignment(variable) {
|
|
6971
|
-
for (const ref of variable.references) {
|
|
6972
|
-
if (!ref.isWrite()) continue;
|
|
6973
|
-
const id = ref.identifier;
|
|
6974
|
-
if (id.parent?.type === AST_NODE_TYPES.AssignmentExpression && id.parent.left === id) {
|
|
6975
|
-
if (isDynamicallyCreatedValue(id.parent.right)) return true;
|
|
6976
|
-
}
|
|
6977
|
-
}
|
|
6978
|
-
return false;
|
|
6979
|
-
}
|
|
6980
|
-
function isDynamicallyCreated(node, variable) {
|
|
6981
|
-
if (node.type === AST_NODE_TYPES.FunctionDeclaration) return true;
|
|
6982
|
-
if (node.type === AST_NODE_TYPES.ClassDeclaration) return true;
|
|
6983
|
-
if (node.type === AST_NODE_TYPES.VariableDeclarator && node.init != null) return isDynamicallyCreatedValue(node.init);
|
|
6984
|
-
if (node.type === AST_NODE_TYPES.VariableDeclarator && node.init == null && variable != null) return hasDynamicAssignment(variable);
|
|
6985
|
-
return false;
|
|
6986
|
-
}
|
|
6987
7029
|
function create$3(context) {
|
|
6988
7030
|
const hint = core.FunctionComponentDetectionHint.DoNotIncludeJsxWithNumberValue | core.FunctionComponentDetectionHint.DoNotIncludeJsxWithBooleanValue | core.FunctionComponentDetectionHint.DoNotIncludeJsxWithNullValue | core.FunctionComponentDetectionHint.DoNotIncludeJsxWithStringValue | core.FunctionComponentDetectionHint.DoNotIncludeJsxWithUndefinedValue | core.FunctionComponentDetectionHint.RequireBothSidesOfLogicalExpressionToBeJsx | core.FunctionComponentDetectionHint.RequireBothBranchesOfConditionalExpressionToBeJsx | core.FunctionComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayPatternElement | core.FunctionComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayExpressionElement | core.FunctionComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayMapCallback;
|
|
6989
7031
|
const fc = core.getFunctionComponentCollector(context, { hint });
|
|
@@ -7009,20 +7051,27 @@ function create$3(context) {
|
|
|
7009
7051
|
return false;
|
|
7010
7052
|
});
|
|
7011
7053
|
}
|
|
7054
|
+
const isInsideRender = (node) => getEnclosingComponent(node) != null;
|
|
7012
7055
|
for (const { name, node: jsxNode } of jsxCandidates) {
|
|
7013
7056
|
const jsxName = jsxNode.name;
|
|
7014
|
-
const variable =
|
|
7057
|
+
const variable = findVariableForIdentifier(context, jsxName);
|
|
7015
7058
|
if (variable == null || variable.defs.length === 0) continue;
|
|
7016
7059
|
const def = variable.defs.at(0);
|
|
7017
7060
|
if (def == null) continue;
|
|
7018
7061
|
const defNode = def.node;
|
|
7019
7062
|
if (getEnclosingComponent(defNode) == null) continue;
|
|
7020
|
-
|
|
7063
|
+
const result = getDynamicComponentSource(context, variable, isInsideRender);
|
|
7064
|
+
if (!result.isDynamic) continue;
|
|
7021
7065
|
context.report({
|
|
7022
7066
|
data: { name },
|
|
7023
7067
|
messageId: "default",
|
|
7024
7068
|
node: jsxNode.name
|
|
7025
7069
|
});
|
|
7070
|
+
if (result.creationNode != null) context.report({
|
|
7071
|
+
data: { name },
|
|
7072
|
+
messageId: "createdHere",
|
|
7073
|
+
node: result.creationNode
|
|
7074
|
+
});
|
|
7026
7075
|
}
|
|
7027
7076
|
}
|
|
7028
7077
|
});
|
|
@@ -7149,11 +7198,11 @@ var use_memo_default = createRule({
|
|
|
7149
7198
|
type: "problem",
|
|
7150
7199
|
docs: { description: "Validates that 'useMemo' is called with a callback that returns a value." },
|
|
7151
7200
|
messages: {
|
|
7152
|
-
|
|
7153
|
-
noAsyncOrGeneratorFunctions: "useMemo() callbacks may not be async or generator functions
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
resultMustBeUsed: "useMemo() result is unused
|
|
7201
|
+
noParameters: "useMemo() callbacks may not accept parameters.\n\nuseMemo() callbacks are called by React to cache calculations across re-renders. They should not take parameters. Instead, directly reference the props, state, or local variables needed for the computation.",
|
|
7202
|
+
noAsyncOrGeneratorFunctions: "useMemo() callbacks may not be async or generator functions.\n\nuseMemo() callbacks are called once and must synchronously return a value.",
|
|
7203
|
+
noReassigningOuterVariables: "useMemo() callbacks may not reassign variables declared outside of the callback.\n\nuseMemo() callbacks must be pure functions and cannot reassign variables defined outside of the callback function.",
|
|
7204
|
+
mustReturnAValue: "useMemo() callbacks must return a value.\n\nThis useMemo() callback doesn't return a value. useMemo() is for computing and caching values, not for arbitrary side effects.",
|
|
7205
|
+
resultMustBeUsed: "useMemo() result is unused.\n\nThis useMemo() value is unused. useMemo() is for computing and caching values, not for arbitrary side effects."
|
|
7157
7206
|
},
|
|
7158
7207
|
schema: []
|
|
7159
7208
|
},
|
|
@@ -7185,7 +7234,7 @@ function create$1(context) {
|
|
|
7185
7234
|
if (!core.isUseMemoCall(context, node)) return;
|
|
7186
7235
|
let parent = node.parent;
|
|
7187
7236
|
while (Check.isTypeExpression(parent)) parent = parent.parent;
|
|
7188
|
-
if (!(parent.type === AST_NODE_TYPES.VariableDeclarator || parent.type === AST_NODE_TYPES.AssignmentExpression || parent.type === AST_NODE_TYPES.AssignmentPattern || parent.type === AST_NODE_TYPES.Property || parent.type === AST_NODE_TYPES.ReturnStatement || parent.type === AST_NODE_TYPES.JSXExpressionContainer || parent.type === AST_NODE_TYPES.CallExpression || parent.type === AST_NODE_TYPES.NewExpression || parent.type === AST_NODE_TYPES.ArrayExpression || parent.type === AST_NODE_TYPES.ConditionalExpression || parent.type === AST_NODE_TYPES.LogicalExpression || parent.type === AST_NODE_TYPES.SequenceExpression || parent.type === AST_NODE_TYPES.SpreadElement || parent.type === AST_NODE_TYPES.TemplateLiteral || parent.type === AST_NODE_TYPES.BinaryExpression || parent.type === AST_NODE_TYPES.UnaryExpression || parent.type === AST_NODE_TYPES.MemberExpression || parent.type === AST_NODE_TYPES.TaggedTemplateExpression || parent.type === AST_NODE_TYPES.ChainExpression || parent.type === AST_NODE_TYPES.ArrowFunctionExpression)) {
|
|
7237
|
+
if (!(parent.type === AST_NODE_TYPES.VariableDeclarator || parent.type === AST_NODE_TYPES.AssignmentExpression || parent.type === AST_NODE_TYPES.AssignmentPattern || parent.type === AST_NODE_TYPES.Property || parent.type === AST_NODE_TYPES.ReturnStatement || parent.type === AST_NODE_TYPES.JSXExpressionContainer || parent.type === AST_NODE_TYPES.CallExpression || parent.type === AST_NODE_TYPES.NewExpression || parent.type === AST_NODE_TYPES.ArrayExpression || parent.type === AST_NODE_TYPES.ConditionalExpression || parent.type === AST_NODE_TYPES.LogicalExpression || parent.type === AST_NODE_TYPES.SequenceExpression || parent.type === AST_NODE_TYPES.SpreadElement || parent.type === AST_NODE_TYPES.TemplateLiteral || parent.type === AST_NODE_TYPES.BinaryExpression || parent.type === AST_NODE_TYPES.UnaryExpression || parent.type === AST_NODE_TYPES.MemberExpression || parent.type === AST_NODE_TYPES.TaggedTemplateExpression || parent.type === AST_NODE_TYPES.ChainExpression || parent.type === AST_NODE_TYPES.ArrowFunctionExpression || parent.type === AST_NODE_TYPES.ForOfStatement || parent.type === AST_NODE_TYPES.ForInStatement)) {
|
|
7189
7238
|
context.report({
|
|
7190
7239
|
messageId: "resultMustBeUsed",
|
|
7191
7240
|
node
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-x",
|
|
3
|
-
"version": "5.5.
|
|
3
|
+
"version": "5.5.3-next.0",
|
|
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",
|
|
@@ -46,12 +46,12 @@
|
|
|
46
46
|
"string-ts": "^2.3.1",
|
|
47
47
|
"ts-api-utils": "^2.5.0",
|
|
48
48
|
"ts-pattern": "^5.9.0",
|
|
49
|
-
"@eslint-react/
|
|
50
|
-
"@eslint-react/
|
|
51
|
-
"@eslint-react/
|
|
52
|
-
"@eslint-react/
|
|
53
|
-
"@eslint-react/
|
|
54
|
-
"@eslint-react/var": "5.5.
|
|
49
|
+
"@eslint-react/ast": "5.5.3-next.0",
|
|
50
|
+
"@eslint-react/core": "5.5.3-next.0",
|
|
51
|
+
"@eslint-react/shared": "5.5.3-next.0",
|
|
52
|
+
"@eslint-react/jsx": "5.5.3-next.0",
|
|
53
|
+
"@eslint-react/eslint": "5.5.3-next.0",
|
|
54
|
+
"@eslint-react/var": "5.5.3-next.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/react": "^19.2.14",
|