eslint-plugin-react-x 1.22.2-beta.5 → 1.22.2-beta.7
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 +75 -127
- package/dist/index.mjs +76 -128
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var eff = require('@eslint-react/eff');
|
|
4
|
-
var
|
|
4
|
+
var JSX7 = require('@eslint-react/jsx');
|
|
5
5
|
var shared = require('@eslint-react/shared');
|
|
6
6
|
var AST11 = require('@eslint-react/ast');
|
|
7
7
|
var core = require('@eslint-react/core');
|
|
@@ -35,14 +35,14 @@ function _interopNamespace(e) {
|
|
|
35
35
|
return Object.freeze(n);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
var
|
|
38
|
+
var JSX7__namespace = /*#__PURE__*/_interopNamespace(JSX7);
|
|
39
39
|
var AST11__namespace = /*#__PURE__*/_interopNamespace(AST11);
|
|
40
40
|
var VAR__namespace = /*#__PURE__*/_interopNamespace(VAR);
|
|
41
41
|
var ts__default = /*#__PURE__*/_interopDefault(ts);
|
|
42
42
|
|
|
43
43
|
// package.json
|
|
44
44
|
var name = "eslint-plugin-react-x";
|
|
45
|
-
var version = "1.22.2-beta.
|
|
45
|
+
var version = "1.22.2-beta.7";
|
|
46
46
|
var createRule = shared.createRuleForPlugin("x");
|
|
47
47
|
|
|
48
48
|
// src/rules/avoid-shorthand-boolean.ts
|
|
@@ -70,7 +70,7 @@ var avoid_shorthand_boolean_default = createRule({
|
|
|
70
70
|
messageId: "avoidShorthandBoolean",
|
|
71
71
|
node,
|
|
72
72
|
data: {
|
|
73
|
-
propName:
|
|
73
|
+
propName: JSX7__namespace.getPropName(node)
|
|
74
74
|
},
|
|
75
75
|
fix: (fixer) => fixer.insertTextAfter(node.name, `={true}`)
|
|
76
76
|
});
|
|
@@ -151,7 +151,7 @@ var RULE_FEATURES4 = [
|
|
|
151
151
|
"CHK"
|
|
152
152
|
];
|
|
153
153
|
function getName(node) {
|
|
154
|
-
if (node
|
|
154
|
+
if (AST11__namespace.isTypeExpression(node)) {
|
|
155
155
|
return getName(node.expression);
|
|
156
156
|
}
|
|
157
157
|
if (node.type === types.AST_NODE_TYPES.Identifier || node.type === types.AST_NODE_TYPES.PrivateIdentifier) {
|
|
@@ -537,7 +537,7 @@ var no_children_prop_default = createRule({
|
|
|
537
537
|
return {
|
|
538
538
|
JSXElement(node) {
|
|
539
539
|
const initialScope = context.sourceCode.getScope(node);
|
|
540
|
-
const prop =
|
|
540
|
+
const prop = JSX7__namespace.getProp(node.openingElement.attributes, "children", initialScope);
|
|
541
541
|
const reportDescriptor = eff.O.map(prop, (prop2) => ({ messageId: "noChildrenProp", node: prop2 }));
|
|
542
542
|
eff.O.map(reportDescriptor, context.report);
|
|
543
543
|
}
|
|
@@ -912,7 +912,7 @@ var no_context_provider_default = createRule({
|
|
|
912
912
|
if (compareVersions.compare(version2, "19.0.0", "<")) return {};
|
|
913
913
|
return {
|
|
914
914
|
JSXElement(node) {
|
|
915
|
-
const elementName =
|
|
915
|
+
const elementName = JSX7__namespace.getElementName(node.openingElement);
|
|
916
916
|
if (!elementName.endsWith(".Provider")) return;
|
|
917
917
|
context.report({
|
|
918
918
|
messageId: "noContextProvider",
|
|
@@ -1009,7 +1009,7 @@ var RULE_FEATURES22 = [
|
|
|
1009
1009
|
"CHK"
|
|
1010
1010
|
];
|
|
1011
1011
|
function getName2(node) {
|
|
1012
|
-
if (node
|
|
1012
|
+
if (AST11__namespace.isTypeExpression(node)) {
|
|
1013
1013
|
return getName2(node.expression);
|
|
1014
1014
|
}
|
|
1015
1015
|
if (node.type === types.AST_NODE_TYPES.Identifier || node.type === types.AST_NODE_TYPES.PrivateIdentifier) {
|
|
@@ -1123,116 +1123,63 @@ var no_duplicate_key_default = createRule({
|
|
|
1123
1123
|
},
|
|
1124
1124
|
name: RULE_NAME24,
|
|
1125
1125
|
create(context) {
|
|
1126
|
-
const
|
|
1127
|
-
function
|
|
1128
|
-
|
|
1126
|
+
const keyedEntries = /* @__PURE__ */ new Map();
|
|
1127
|
+
function isKeyValueEqual(a, b) {
|
|
1128
|
+
const aValue = a.value;
|
|
1129
|
+
const bValue = b.value;
|
|
1130
|
+
if (aValue === null || bValue === null) return false;
|
|
1131
|
+
return VAR__namespace.isNodeValueEqual(aValue, bValue, [
|
|
1132
|
+
context.sourceCode.getScope(aValue),
|
|
1133
|
+
context.sourceCode.getScope(bValue)
|
|
1134
|
+
]);
|
|
1129
1135
|
}
|
|
1130
|
-
function checkIteratorElement(node) {
|
|
1131
|
-
if (node.type !== types.AST_NODE_TYPES.JSXElement) return eff.O.none();
|
|
1132
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
1133
|
-
return eff.F.pipe(
|
|
1134
|
-
JSX8__namespace.findPropInAttributes(node.openingElement.attributes, initialScope)("key"),
|
|
1135
|
-
eff.O.flatMap((k) => "value" in k ? eff.O.fromNullable(k.value) : eff.O.none()),
|
|
1136
|
-
eff.O.flatMap((v) => {
|
|
1137
|
-
return isKeyEqual(v, v) ? eff.O.some({
|
|
1138
|
-
messageId: "noDuplicateKey",
|
|
1139
|
-
node: v,
|
|
1140
|
-
data: {
|
|
1141
|
-
value: context.sourceCode.getText(v)
|
|
1142
|
-
}
|
|
1143
|
-
}) : eff.O.none();
|
|
1144
|
-
})
|
|
1145
|
-
);
|
|
1146
|
-
}
|
|
1147
|
-
function checkExpression(node) {
|
|
1148
|
-
switch (node.type) {
|
|
1149
|
-
case types.AST_NODE_TYPES.ConditionalExpression:
|
|
1150
|
-
if (!("consequent" in node)) return eff.O.none();
|
|
1151
|
-
return eff.F.pipe(
|
|
1152
|
-
checkIteratorElement(node.consequent),
|
|
1153
|
-
eff.O.orElse(() => checkIteratorElement(node.alternate))
|
|
1154
|
-
);
|
|
1155
|
-
case types.AST_NODE_TYPES.JSXElement:
|
|
1156
|
-
case types.AST_NODE_TYPES.JSXFragment:
|
|
1157
|
-
return checkIteratorElement(node);
|
|
1158
|
-
case types.AST_NODE_TYPES.LogicalExpression:
|
|
1159
|
-
if (!("left" in node)) return eff.O.none();
|
|
1160
|
-
return eff.F.pipe(
|
|
1161
|
-
checkIteratorElement(node.left),
|
|
1162
|
-
eff.O.orElse(() => checkIteratorElement(node.right))
|
|
1163
|
-
);
|
|
1164
|
-
default:
|
|
1165
|
-
return eff.O.none();
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
|
-
function checkBlockStatement(node) {
|
|
1169
|
-
return AST11__namespace.getNestedReturnStatements(node).reduce((acc, statement) => {
|
|
1170
|
-
if (!statement.argument) return acc;
|
|
1171
|
-
const maybeDescriptor = checkIteratorElement(statement.argument);
|
|
1172
|
-
if (eff.O.isNone(maybeDescriptor)) return acc;
|
|
1173
|
-
const descriptor = maybeDescriptor.value;
|
|
1174
|
-
return [...acc, descriptor];
|
|
1175
|
-
}, []);
|
|
1176
|
-
}
|
|
1177
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
1178
1136
|
return {
|
|
1179
|
-
"
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1137
|
+
"JSXAttribute[name.name='key']"(node) {
|
|
1138
|
+
const jsxElement = node.parent.parent;
|
|
1139
|
+
switch (jsxElement.parent.type) {
|
|
1140
|
+
case types.AST_NODE_TYPES.ArrayExpression:
|
|
1141
|
+
case types.AST_NODE_TYPES.JSXElement:
|
|
1142
|
+
case types.AST_NODE_TYPES.JSXFragment: {
|
|
1143
|
+
const root = jsxElement.parent;
|
|
1144
|
+
const prevKeys = keyedEntries.get(root)?.keys ?? [];
|
|
1145
|
+
keyedEntries.set(root, {
|
|
1146
|
+
hasDuplicate: prevKeys.some((prevKey) => isKeyValueEqual(prevKey, node)),
|
|
1147
|
+
keys: [...prevKeys, node],
|
|
1148
|
+
root: jsxElement.parent
|
|
1187
1149
|
});
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
data: {
|
|
1205
|
-
value: context.sourceCode.getText(value)
|
|
1150
|
+
break;
|
|
1151
|
+
}
|
|
1152
|
+
default: {
|
|
1153
|
+
const entry = eff.F.pipe(
|
|
1154
|
+
eff.O.Do,
|
|
1155
|
+
eff.O.bind("call", () => AST11__namespace.traverseUpGuard(jsxElement, AST11__namespace.isMapCallLoose)),
|
|
1156
|
+
eff.O.bind("iter", ({ call }) => AST11__namespace.traverseUpStop(jsxElement, call, AST11__namespace.isFunction)),
|
|
1157
|
+
eff.O.bind("arg0", ({ call }) => eff.O.fromNullable(call.arguments[0]))
|
|
1158
|
+
);
|
|
1159
|
+
for (const { arg0, call, iter } of eff.O.toArray(entry)) {
|
|
1160
|
+
if (AST11__namespace.unwrapTypeExpression(arg0) !== iter) continue;
|
|
1161
|
+
keyedEntries.set(call, {
|
|
1162
|
+
hasDuplicate: node.value?.type === types.AST_NODE_TYPES.Literal,
|
|
1163
|
+
keys: [node],
|
|
1164
|
+
root: call
|
|
1165
|
+
});
|
|
1206
1166
|
}
|
|
1207
|
-
}
|
|
1167
|
+
}
|
|
1208
1168
|
}
|
|
1209
1169
|
},
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
}, node);
|
|
1222
|
-
if (!isMapCall && !isArrayFromCall) return;
|
|
1223
|
-
if (eff.MutRef.get(isWithinChildrenToArrayRef)) return;
|
|
1224
|
-
const fn = node.arguments[isMapCall ? 0 : 1];
|
|
1225
|
-
if (!AST11__namespace.isOneOf([types.AST_NODE_TYPES.ArrowFunctionExpression, types.AST_NODE_TYPES.FunctionExpression])(fn)) return;
|
|
1226
|
-
if (fn.body.type === types.AST_NODE_TYPES.BlockStatement) {
|
|
1227
|
-
for (const descriptor of checkBlockStatement(fn.body)) {
|
|
1228
|
-
context.report(descriptor);
|
|
1170
|
+
"Program:exit"() {
|
|
1171
|
+
for (const { hasDuplicate, keys } of keyedEntries.values()) {
|
|
1172
|
+
if (!hasDuplicate) continue;
|
|
1173
|
+
for (const key of keys) {
|
|
1174
|
+
context.report({
|
|
1175
|
+
messageId: "noDuplicateKey",
|
|
1176
|
+
node: key,
|
|
1177
|
+
data: {
|
|
1178
|
+
value: context.sourceCode.getText(key)
|
|
1179
|
+
}
|
|
1180
|
+
});
|
|
1229
1181
|
}
|
|
1230
|
-
return;
|
|
1231
1182
|
}
|
|
1232
|
-
eff.O.map(checkExpression(fn.body), context.report);
|
|
1233
|
-
},
|
|
1234
|
-
"CallExpression:exit"(node) {
|
|
1235
|
-
if (core.isChildrenToArrayCall(node, context)) eff.MutRef.set(isWithinChildrenToArrayRef, false);
|
|
1236
1183
|
}
|
|
1237
1184
|
};
|
|
1238
1185
|
},
|
|
@@ -1355,7 +1302,7 @@ var no_implicit_key_default = createRule({
|
|
|
1355
1302
|
create(context) {
|
|
1356
1303
|
function getReportDescriptor(node) {
|
|
1357
1304
|
const initialScope = context.sourceCode.getScope(node);
|
|
1358
|
-
const keyPropFound =
|
|
1305
|
+
const keyPropFound = JSX7__namespace.findPropInAttributes(node.attributes, initialScope)("key");
|
|
1359
1306
|
const keyPropOnElement = node.attributes.some(
|
|
1360
1307
|
(n) => AST11__namespace.is(types.AST_NODE_TYPES.JSXAttribute)(n) && n.name.name === "key"
|
|
1361
1308
|
);
|
|
@@ -1595,12 +1542,12 @@ var no_missing_key_default = createRule({
|
|
|
1595
1542
|
},
|
|
1596
1543
|
name: RULE_NAME29,
|
|
1597
1544
|
create(context) {
|
|
1598
|
-
const
|
|
1545
|
+
const state = { isWithinChildrenToArray: false };
|
|
1599
1546
|
function checkIteratorElement(node) {
|
|
1600
1547
|
switch (node.type) {
|
|
1601
1548
|
case types.AST_NODE_TYPES.JSXElement: {
|
|
1602
1549
|
const initialScope = context.sourceCode.getScope(node);
|
|
1603
|
-
if (!
|
|
1550
|
+
if (!JSX7__namespace.hasProp(node.openingElement.attributes, "key", initialScope)) {
|
|
1604
1551
|
return eff.O.some({
|
|
1605
1552
|
messageId: "noMissingKey",
|
|
1606
1553
|
node
|
|
@@ -1644,12 +1591,12 @@ var no_missing_key_default = createRule({
|
|
|
1644
1591
|
}
|
|
1645
1592
|
return {
|
|
1646
1593
|
ArrayExpression(node) {
|
|
1647
|
-
if (
|
|
1594
|
+
if (state.isWithinChildrenToArray) return;
|
|
1648
1595
|
const elements = node.elements.filter(AST11__namespace.is(types.AST_NODE_TYPES.JSXElement));
|
|
1649
1596
|
if (elements.length === 0) return;
|
|
1650
1597
|
const initialScope = context.sourceCode.getScope(node);
|
|
1651
1598
|
for (const element of elements) {
|
|
1652
|
-
if (!
|
|
1599
|
+
if (!JSX7__namespace.hasProp(element.openingElement.attributes, "key", initialScope)) {
|
|
1653
1600
|
context.report({
|
|
1654
1601
|
messageId: "noMissingKey",
|
|
1655
1602
|
node: element
|
|
@@ -1658,7 +1605,8 @@ var no_missing_key_default = createRule({
|
|
|
1658
1605
|
}
|
|
1659
1606
|
},
|
|
1660
1607
|
CallExpression(node) {
|
|
1661
|
-
|
|
1608
|
+
state.isWithinChildrenToArray ||= core.isChildrenToArrayCall(node, context);
|
|
1609
|
+
if (state.isWithinChildrenToArray) return;
|
|
1662
1610
|
const isMapCall = AST11__namespace.isMapCallLoose(node);
|
|
1663
1611
|
const isArrayFromCall = tsPattern.isMatching({
|
|
1664
1612
|
type: types.AST_NODE_TYPES.CallExpression,
|
|
@@ -1670,7 +1618,6 @@ var no_missing_key_default = createRule({
|
|
|
1670
1618
|
}
|
|
1671
1619
|
}, node);
|
|
1672
1620
|
if (!isMapCall && !isArrayFromCall) return;
|
|
1673
|
-
if (eff.MutRef.get(isWithinChildrenToArrayRef)) return;
|
|
1674
1621
|
const fn = node.arguments[isMapCall ? 0 : 1];
|
|
1675
1622
|
if (!AST11__namespace.isOneOf([types.AST_NODE_TYPES.ArrowFunctionExpression, types.AST_NODE_TYPES.FunctionExpression])(fn)) return;
|
|
1676
1623
|
if (fn.body.type === types.AST_NODE_TYPES.BlockStatement) {
|
|
@@ -1682,10 +1629,11 @@ var no_missing_key_default = createRule({
|
|
|
1682
1629
|
eff.O.map(checkExpression(fn.body), context.report);
|
|
1683
1630
|
},
|
|
1684
1631
|
"CallExpression:exit"(node) {
|
|
1685
|
-
if (core.isChildrenToArrayCall(node, context))
|
|
1632
|
+
if (!core.isChildrenToArrayCall(node, context)) return;
|
|
1633
|
+
state.isWithinChildrenToArray = false;
|
|
1686
1634
|
},
|
|
1687
1635
|
JSXFragment(node) {
|
|
1688
|
-
if (
|
|
1636
|
+
if (state.isWithinChildrenToArray) return;
|
|
1689
1637
|
if (node.parent.type === types.AST_NODE_TYPES.ArrayExpression) {
|
|
1690
1638
|
context.report({
|
|
1691
1639
|
messageId: "noMissingKeyWithFragment",
|
|
@@ -1736,7 +1684,7 @@ var no_nested_components_default = createRule({
|
|
|
1736
1684
|
if (eff.O.isNone(componentName)) continue;
|
|
1737
1685
|
const name2 = componentName.value;
|
|
1738
1686
|
const isInsideProperty = component.parent.type === types.AST_NODE_TYPES.Property;
|
|
1739
|
-
const isInsideJSXPropValue = component.parent.type === types.AST_NODE_TYPES.JSXAttribute || eff.O.isSome(
|
|
1687
|
+
const isInsideJSXPropValue = component.parent.type === types.AST_NODE_TYPES.JSXAttribute || eff.O.isSome(JSX7__namespace.traverseUpProp(node, (n) => n.value?.type === types.AST_NODE_TYPES.JSXExpressionContainer));
|
|
1740
1688
|
if (isInsideJSXPropValue) {
|
|
1741
1689
|
if (!core.isDeclaredInRenderPropLoose(component)) {
|
|
1742
1690
|
context.report({
|
|
@@ -2360,7 +2308,7 @@ var LIFECYCLE_METHODS = /* @__PURE__ */ new Set([
|
|
|
2360
2308
|
"UNSAFE_componentWillUpdate"
|
|
2361
2309
|
]);
|
|
2362
2310
|
function getName3(node) {
|
|
2363
|
-
if (node
|
|
2311
|
+
if (AST11__namespace.isTypeExpression(node)) {
|
|
2364
2312
|
return getName3(node.expression);
|
|
2365
2313
|
}
|
|
2366
2314
|
if (node.type === types.AST_NODE_TYPES.Identifier || node.type === types.AST_NODE_TYPES.PrivateIdentifier) {
|
|
@@ -2474,7 +2422,7 @@ var RULE_FEATURES43 = [
|
|
|
2474
2422
|
"CHK"
|
|
2475
2423
|
];
|
|
2476
2424
|
function getName4(node) {
|
|
2477
|
-
if (node
|
|
2425
|
+
if (AST11__namespace.isTypeExpression(node)) {
|
|
2478
2426
|
return getName4(node.expression);
|
|
2479
2427
|
}
|
|
2480
2428
|
if (node.type === types.AST_NODE_TYPES.Identifier || node.type === types.AST_NODE_TYPES.PrivateIdentifier) {
|
|
@@ -2617,18 +2565,18 @@ var no_unused_state_default = createRule({
|
|
|
2617
2565
|
var RULE_NAME44 = "no-useless-fragment";
|
|
2618
2566
|
function check(node, context, allowExpressions) {
|
|
2619
2567
|
const initialScope = context.sourceCode.getScope(node);
|
|
2620
|
-
if (
|
|
2621
|
-
if (
|
|
2568
|
+
if (JSX7__namespace.isKeyedElement(node, initialScope)) return;
|
|
2569
|
+
if (JSX7__namespace.isBuiltInElement(node.parent)) context.report({ messageId: "noUselessFragmentInBuiltIn", node });
|
|
2622
2570
|
if (node.children.length === 0) return context.report({ messageId: "noUselessFragment", node });
|
|
2623
2571
|
const isChildren = AST11__namespace.isOneOf([types.AST_NODE_TYPES.JSXElement, types.AST_NODE_TYPES.JSXFragment])(node.parent);
|
|
2624
2572
|
const [firstChildren] = node.children;
|
|
2625
|
-
if (allowExpressions && node.children.length === 1 &&
|
|
2573
|
+
if (allowExpressions && node.children.length === 1 && JSX7__namespace.isLiteral(firstChildren) && !isChildren) return;
|
|
2626
2574
|
if (!allowExpressions && isChildren) {
|
|
2627
2575
|
return context.report({ messageId: "noUselessFragment", node });
|
|
2628
2576
|
} else if (!allowExpressions && !isChildren && node.children.length === 1) {
|
|
2629
2577
|
return context.report({ messageId: "noUselessFragment", node });
|
|
2630
2578
|
}
|
|
2631
|
-
const nonPaddingChildren = node.children.filter((child) => !
|
|
2579
|
+
const nonPaddingChildren = node.children.filter((child) => !JSX7__namespace.isPaddingSpaces(child));
|
|
2632
2580
|
if (nonPaddingChildren.length > 1) return;
|
|
2633
2581
|
if (nonPaddingChildren.length === 0) return context.report({ messageId: "noUselessFragment", node });
|
|
2634
2582
|
const [first] = nonPaddingChildren;
|
|
@@ -2870,7 +2818,7 @@ var prefer_shorthand_boolean_default = createRule({
|
|
|
2870
2818
|
create(context) {
|
|
2871
2819
|
function getReportDescriptor(node) {
|
|
2872
2820
|
const { value } = node;
|
|
2873
|
-
const propName =
|
|
2821
|
+
const propName = JSX7__namespace.getPropName(node);
|
|
2874
2822
|
const hasValueTrue = value?.type === types.AST_NODE_TYPES.JSXExpressionContainer && value.expression.type === types.AST_NODE_TYPES.Literal && value.expression.value === true;
|
|
2875
2823
|
if (!hasValueTrue) return eff.O.none();
|
|
2876
2824
|
return eff.O.some({
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { F, O, isString,
|
|
2
|
-
import * as
|
|
1
|
+
import { F, O, isString, isNullable } from '@eslint-react/eff';
|
|
2
|
+
import * as JSX7 from '@eslint-react/jsx';
|
|
3
3
|
import { createRuleForPlugin, normalizeSettings, decodeSettings, unsafeReadSettings } from '@eslint-react/shared';
|
|
4
4
|
import * as AST11 from '@eslint-react/ast';
|
|
5
|
-
import { isForwardRefCall, isThisSetState, isClassComponent, isChildrenCount, isChildrenForEach, isChildrenMap, isChildrenOnly, isChildrenToArray, useComponentCollectorLegacy, isCloneElementCall, isCreateRefCall, isComponentName,
|
|
5
|
+
import { isForwardRefCall, isThisSetState, isClassComponent, isChildrenCount, isChildrenForEach, isChildrenMap, isChildrenOnly, isChildrenToArray, useComponentCollectorLegacy, isCloneElementCall, isCreateRefCall, isComponentName, useComponentCollector, ERFunctionComponentFlag, isChildrenToArrayCall, ERComponentHint, isDirectValueOfRenderPropertyLoose, isDeclaredInRenderPropLoose, isInsideCreateElementProps, isInsideRenderMethod, ERClassComponentFlag, isFragmentElement, isCreateElementCall, isInitializedFromReact } from '@eslint-react/core';
|
|
6
6
|
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
7
7
|
import { isMatching, P, match } from 'ts-pattern';
|
|
8
8
|
import { compare } from 'compare-versions';
|
|
@@ -15,7 +15,7 @@ import { getTypeImmutability, isUnknown, isImmutable, isReadonlyShallow, isReado
|
|
|
15
15
|
|
|
16
16
|
// package.json
|
|
17
17
|
var name = "eslint-plugin-react-x";
|
|
18
|
-
var version = "1.22.2-beta.
|
|
18
|
+
var version = "1.22.2-beta.7";
|
|
19
19
|
var createRule = createRuleForPlugin("x");
|
|
20
20
|
|
|
21
21
|
// src/rules/avoid-shorthand-boolean.ts
|
|
@@ -43,7 +43,7 @@ var avoid_shorthand_boolean_default = createRule({
|
|
|
43
43
|
messageId: "avoidShorthandBoolean",
|
|
44
44
|
node,
|
|
45
45
|
data: {
|
|
46
|
-
propName:
|
|
46
|
+
propName: JSX7.getPropName(node)
|
|
47
47
|
},
|
|
48
48
|
fix: (fixer) => fixer.insertTextAfter(node.name, `={true}`)
|
|
49
49
|
});
|
|
@@ -124,7 +124,7 @@ var RULE_FEATURES4 = [
|
|
|
124
124
|
"CHK"
|
|
125
125
|
];
|
|
126
126
|
function getName(node) {
|
|
127
|
-
if (node
|
|
127
|
+
if (AST11.isTypeExpression(node)) {
|
|
128
128
|
return getName(node.expression);
|
|
129
129
|
}
|
|
130
130
|
if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) {
|
|
@@ -510,7 +510,7 @@ var no_children_prop_default = createRule({
|
|
|
510
510
|
return {
|
|
511
511
|
JSXElement(node) {
|
|
512
512
|
const initialScope = context.sourceCode.getScope(node);
|
|
513
|
-
const prop =
|
|
513
|
+
const prop = JSX7.getProp(node.openingElement.attributes, "children", initialScope);
|
|
514
514
|
const reportDescriptor = O.map(prop, (prop2) => ({ messageId: "noChildrenProp", node: prop2 }));
|
|
515
515
|
O.map(reportDescriptor, context.report);
|
|
516
516
|
}
|
|
@@ -885,7 +885,7 @@ var no_context_provider_default = createRule({
|
|
|
885
885
|
if (compare(version2, "19.0.0", "<")) return {};
|
|
886
886
|
return {
|
|
887
887
|
JSXElement(node) {
|
|
888
|
-
const elementName =
|
|
888
|
+
const elementName = JSX7.getElementName(node.openingElement);
|
|
889
889
|
if (!elementName.endsWith(".Provider")) return;
|
|
890
890
|
context.report({
|
|
891
891
|
messageId: "noContextProvider",
|
|
@@ -982,7 +982,7 @@ var RULE_FEATURES22 = [
|
|
|
982
982
|
"CHK"
|
|
983
983
|
];
|
|
984
984
|
function getName2(node) {
|
|
985
|
-
if (node
|
|
985
|
+
if (AST11.isTypeExpression(node)) {
|
|
986
986
|
return getName2(node.expression);
|
|
987
987
|
}
|
|
988
988
|
if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) {
|
|
@@ -1096,116 +1096,63 @@ var no_duplicate_key_default = createRule({
|
|
|
1096
1096
|
},
|
|
1097
1097
|
name: RULE_NAME24,
|
|
1098
1098
|
create(context) {
|
|
1099
|
-
const
|
|
1100
|
-
function
|
|
1101
|
-
|
|
1099
|
+
const keyedEntries = /* @__PURE__ */ new Map();
|
|
1100
|
+
function isKeyValueEqual(a, b) {
|
|
1101
|
+
const aValue = a.value;
|
|
1102
|
+
const bValue = b.value;
|
|
1103
|
+
if (aValue === null || bValue === null) return false;
|
|
1104
|
+
return VAR.isNodeValueEqual(aValue, bValue, [
|
|
1105
|
+
context.sourceCode.getScope(aValue),
|
|
1106
|
+
context.sourceCode.getScope(bValue)
|
|
1107
|
+
]);
|
|
1102
1108
|
}
|
|
1103
|
-
function checkIteratorElement(node) {
|
|
1104
|
-
if (node.type !== AST_NODE_TYPES.JSXElement) return O.none();
|
|
1105
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
1106
|
-
return F.pipe(
|
|
1107
|
-
JSX8.findPropInAttributes(node.openingElement.attributes, initialScope)("key"),
|
|
1108
|
-
O.flatMap((k) => "value" in k ? O.fromNullable(k.value) : O.none()),
|
|
1109
|
-
O.flatMap((v) => {
|
|
1110
|
-
return isKeyEqual(v, v) ? O.some({
|
|
1111
|
-
messageId: "noDuplicateKey",
|
|
1112
|
-
node: v,
|
|
1113
|
-
data: {
|
|
1114
|
-
value: context.sourceCode.getText(v)
|
|
1115
|
-
}
|
|
1116
|
-
}) : O.none();
|
|
1117
|
-
})
|
|
1118
|
-
);
|
|
1119
|
-
}
|
|
1120
|
-
function checkExpression(node) {
|
|
1121
|
-
switch (node.type) {
|
|
1122
|
-
case AST_NODE_TYPES.ConditionalExpression:
|
|
1123
|
-
if (!("consequent" in node)) return O.none();
|
|
1124
|
-
return F.pipe(
|
|
1125
|
-
checkIteratorElement(node.consequent),
|
|
1126
|
-
O.orElse(() => checkIteratorElement(node.alternate))
|
|
1127
|
-
);
|
|
1128
|
-
case AST_NODE_TYPES.JSXElement:
|
|
1129
|
-
case AST_NODE_TYPES.JSXFragment:
|
|
1130
|
-
return checkIteratorElement(node);
|
|
1131
|
-
case AST_NODE_TYPES.LogicalExpression:
|
|
1132
|
-
if (!("left" in node)) return O.none();
|
|
1133
|
-
return F.pipe(
|
|
1134
|
-
checkIteratorElement(node.left),
|
|
1135
|
-
O.orElse(() => checkIteratorElement(node.right))
|
|
1136
|
-
);
|
|
1137
|
-
default:
|
|
1138
|
-
return O.none();
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
function checkBlockStatement(node) {
|
|
1142
|
-
return AST11.getNestedReturnStatements(node).reduce((acc, statement) => {
|
|
1143
|
-
if (!statement.argument) return acc;
|
|
1144
|
-
const maybeDescriptor = checkIteratorElement(statement.argument);
|
|
1145
|
-
if (O.isNone(maybeDescriptor)) return acc;
|
|
1146
|
-
const descriptor = maybeDescriptor.value;
|
|
1147
|
-
return [...acc, descriptor];
|
|
1148
|
-
}, []);
|
|
1149
|
-
}
|
|
1150
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
1151
1109
|
return {
|
|
1152
|
-
"
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1110
|
+
"JSXAttribute[name.name='key']"(node) {
|
|
1111
|
+
const jsxElement = node.parent.parent;
|
|
1112
|
+
switch (jsxElement.parent.type) {
|
|
1113
|
+
case AST_NODE_TYPES.ArrayExpression:
|
|
1114
|
+
case AST_NODE_TYPES.JSXElement:
|
|
1115
|
+
case AST_NODE_TYPES.JSXFragment: {
|
|
1116
|
+
const root = jsxElement.parent;
|
|
1117
|
+
const prevKeys = keyedEntries.get(root)?.keys ?? [];
|
|
1118
|
+
keyedEntries.set(root, {
|
|
1119
|
+
hasDuplicate: prevKeys.some((prevKey) => isKeyValueEqual(prevKey, node)),
|
|
1120
|
+
keys: [...prevKeys, node],
|
|
1121
|
+
root: jsxElement.parent
|
|
1160
1122
|
});
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
data: {
|
|
1178
|
-
value: context.sourceCode.getText(value)
|
|
1123
|
+
break;
|
|
1124
|
+
}
|
|
1125
|
+
default: {
|
|
1126
|
+
const entry = F.pipe(
|
|
1127
|
+
O.Do,
|
|
1128
|
+
O.bind("call", () => AST11.traverseUpGuard(jsxElement, AST11.isMapCallLoose)),
|
|
1129
|
+
O.bind("iter", ({ call }) => AST11.traverseUpStop(jsxElement, call, AST11.isFunction)),
|
|
1130
|
+
O.bind("arg0", ({ call }) => O.fromNullable(call.arguments[0]))
|
|
1131
|
+
);
|
|
1132
|
+
for (const { arg0, call, iter } of O.toArray(entry)) {
|
|
1133
|
+
if (AST11.unwrapTypeExpression(arg0) !== iter) continue;
|
|
1134
|
+
keyedEntries.set(call, {
|
|
1135
|
+
hasDuplicate: node.value?.type === AST_NODE_TYPES.Literal,
|
|
1136
|
+
keys: [node],
|
|
1137
|
+
root: call
|
|
1138
|
+
});
|
|
1179
1139
|
}
|
|
1180
|
-
}
|
|
1140
|
+
}
|
|
1181
1141
|
}
|
|
1182
1142
|
},
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
}, node);
|
|
1195
|
-
if (!isMapCall && !isArrayFromCall) return;
|
|
1196
|
-
if (MutRef.get(isWithinChildrenToArrayRef)) return;
|
|
1197
|
-
const fn = node.arguments[isMapCall ? 0 : 1];
|
|
1198
|
-
if (!AST11.isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(fn)) return;
|
|
1199
|
-
if (fn.body.type === AST_NODE_TYPES.BlockStatement) {
|
|
1200
|
-
for (const descriptor of checkBlockStatement(fn.body)) {
|
|
1201
|
-
context.report(descriptor);
|
|
1143
|
+
"Program:exit"() {
|
|
1144
|
+
for (const { hasDuplicate, keys } of keyedEntries.values()) {
|
|
1145
|
+
if (!hasDuplicate) continue;
|
|
1146
|
+
for (const key of keys) {
|
|
1147
|
+
context.report({
|
|
1148
|
+
messageId: "noDuplicateKey",
|
|
1149
|
+
node: key,
|
|
1150
|
+
data: {
|
|
1151
|
+
value: context.sourceCode.getText(key)
|
|
1152
|
+
}
|
|
1153
|
+
});
|
|
1202
1154
|
}
|
|
1203
|
-
return;
|
|
1204
1155
|
}
|
|
1205
|
-
O.map(checkExpression(fn.body), context.report);
|
|
1206
|
-
},
|
|
1207
|
-
"CallExpression:exit"(node) {
|
|
1208
|
-
if (isChildrenToArrayCall(node, context)) MutRef.set(isWithinChildrenToArrayRef, false);
|
|
1209
1156
|
}
|
|
1210
1157
|
};
|
|
1211
1158
|
},
|
|
@@ -1328,7 +1275,7 @@ var no_implicit_key_default = createRule({
|
|
|
1328
1275
|
create(context) {
|
|
1329
1276
|
function getReportDescriptor(node) {
|
|
1330
1277
|
const initialScope = context.sourceCode.getScope(node);
|
|
1331
|
-
const keyPropFound =
|
|
1278
|
+
const keyPropFound = JSX7.findPropInAttributes(node.attributes, initialScope)("key");
|
|
1332
1279
|
const keyPropOnElement = node.attributes.some(
|
|
1333
1280
|
(n) => AST11.is(AST_NODE_TYPES.JSXAttribute)(n) && n.name.name === "key"
|
|
1334
1281
|
);
|
|
@@ -1568,12 +1515,12 @@ var no_missing_key_default = createRule({
|
|
|
1568
1515
|
},
|
|
1569
1516
|
name: RULE_NAME29,
|
|
1570
1517
|
create(context) {
|
|
1571
|
-
const
|
|
1518
|
+
const state = { isWithinChildrenToArray: false };
|
|
1572
1519
|
function checkIteratorElement(node) {
|
|
1573
1520
|
switch (node.type) {
|
|
1574
1521
|
case AST_NODE_TYPES.JSXElement: {
|
|
1575
1522
|
const initialScope = context.sourceCode.getScope(node);
|
|
1576
|
-
if (!
|
|
1523
|
+
if (!JSX7.hasProp(node.openingElement.attributes, "key", initialScope)) {
|
|
1577
1524
|
return O.some({
|
|
1578
1525
|
messageId: "noMissingKey",
|
|
1579
1526
|
node
|
|
@@ -1617,12 +1564,12 @@ var no_missing_key_default = createRule({
|
|
|
1617
1564
|
}
|
|
1618
1565
|
return {
|
|
1619
1566
|
ArrayExpression(node) {
|
|
1620
|
-
if (
|
|
1567
|
+
if (state.isWithinChildrenToArray) return;
|
|
1621
1568
|
const elements = node.elements.filter(AST11.is(AST_NODE_TYPES.JSXElement));
|
|
1622
1569
|
if (elements.length === 0) return;
|
|
1623
1570
|
const initialScope = context.sourceCode.getScope(node);
|
|
1624
1571
|
for (const element of elements) {
|
|
1625
|
-
if (!
|
|
1572
|
+
if (!JSX7.hasProp(element.openingElement.attributes, "key", initialScope)) {
|
|
1626
1573
|
context.report({
|
|
1627
1574
|
messageId: "noMissingKey",
|
|
1628
1575
|
node: element
|
|
@@ -1631,7 +1578,8 @@ var no_missing_key_default = createRule({
|
|
|
1631
1578
|
}
|
|
1632
1579
|
},
|
|
1633
1580
|
CallExpression(node) {
|
|
1634
|
-
|
|
1581
|
+
state.isWithinChildrenToArray ||= isChildrenToArrayCall(node, context);
|
|
1582
|
+
if (state.isWithinChildrenToArray) return;
|
|
1635
1583
|
const isMapCall = AST11.isMapCallLoose(node);
|
|
1636
1584
|
const isArrayFromCall = isMatching({
|
|
1637
1585
|
type: AST_NODE_TYPES.CallExpression,
|
|
@@ -1643,7 +1591,6 @@ var no_missing_key_default = createRule({
|
|
|
1643
1591
|
}
|
|
1644
1592
|
}, node);
|
|
1645
1593
|
if (!isMapCall && !isArrayFromCall) return;
|
|
1646
|
-
if (MutRef.get(isWithinChildrenToArrayRef)) return;
|
|
1647
1594
|
const fn = node.arguments[isMapCall ? 0 : 1];
|
|
1648
1595
|
if (!AST11.isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(fn)) return;
|
|
1649
1596
|
if (fn.body.type === AST_NODE_TYPES.BlockStatement) {
|
|
@@ -1655,10 +1602,11 @@ var no_missing_key_default = createRule({
|
|
|
1655
1602
|
O.map(checkExpression(fn.body), context.report);
|
|
1656
1603
|
},
|
|
1657
1604
|
"CallExpression:exit"(node) {
|
|
1658
|
-
if (isChildrenToArrayCall(node, context))
|
|
1605
|
+
if (!isChildrenToArrayCall(node, context)) return;
|
|
1606
|
+
state.isWithinChildrenToArray = false;
|
|
1659
1607
|
},
|
|
1660
1608
|
JSXFragment(node) {
|
|
1661
|
-
if (
|
|
1609
|
+
if (state.isWithinChildrenToArray) return;
|
|
1662
1610
|
if (node.parent.type === AST_NODE_TYPES.ArrayExpression) {
|
|
1663
1611
|
context.report({
|
|
1664
1612
|
messageId: "noMissingKeyWithFragment",
|
|
@@ -1709,7 +1657,7 @@ var no_nested_components_default = createRule({
|
|
|
1709
1657
|
if (O.isNone(componentName)) continue;
|
|
1710
1658
|
const name2 = componentName.value;
|
|
1711
1659
|
const isInsideProperty = component.parent.type === AST_NODE_TYPES.Property;
|
|
1712
|
-
const isInsideJSXPropValue = component.parent.type === AST_NODE_TYPES.JSXAttribute || O.isSome(
|
|
1660
|
+
const isInsideJSXPropValue = component.parent.type === AST_NODE_TYPES.JSXAttribute || O.isSome(JSX7.traverseUpProp(node, (n) => n.value?.type === AST_NODE_TYPES.JSXExpressionContainer));
|
|
1713
1661
|
if (isInsideJSXPropValue) {
|
|
1714
1662
|
if (!isDeclaredInRenderPropLoose(component)) {
|
|
1715
1663
|
context.report({
|
|
@@ -2333,7 +2281,7 @@ var LIFECYCLE_METHODS = /* @__PURE__ */ new Set([
|
|
|
2333
2281
|
"UNSAFE_componentWillUpdate"
|
|
2334
2282
|
]);
|
|
2335
2283
|
function getName3(node) {
|
|
2336
|
-
if (node
|
|
2284
|
+
if (AST11.isTypeExpression(node)) {
|
|
2337
2285
|
return getName3(node.expression);
|
|
2338
2286
|
}
|
|
2339
2287
|
if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) {
|
|
@@ -2447,7 +2395,7 @@ var RULE_FEATURES43 = [
|
|
|
2447
2395
|
"CHK"
|
|
2448
2396
|
];
|
|
2449
2397
|
function getName4(node) {
|
|
2450
|
-
if (node
|
|
2398
|
+
if (AST11.isTypeExpression(node)) {
|
|
2451
2399
|
return getName4(node.expression);
|
|
2452
2400
|
}
|
|
2453
2401
|
if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) {
|
|
@@ -2590,18 +2538,18 @@ var no_unused_state_default = createRule({
|
|
|
2590
2538
|
var RULE_NAME44 = "no-useless-fragment";
|
|
2591
2539
|
function check(node, context, allowExpressions) {
|
|
2592
2540
|
const initialScope = context.sourceCode.getScope(node);
|
|
2593
|
-
if (
|
|
2594
|
-
if (
|
|
2541
|
+
if (JSX7.isKeyedElement(node, initialScope)) return;
|
|
2542
|
+
if (JSX7.isBuiltInElement(node.parent)) context.report({ messageId: "noUselessFragmentInBuiltIn", node });
|
|
2595
2543
|
if (node.children.length === 0) return context.report({ messageId: "noUselessFragment", node });
|
|
2596
2544
|
const isChildren = AST11.isOneOf([AST_NODE_TYPES.JSXElement, AST_NODE_TYPES.JSXFragment])(node.parent);
|
|
2597
2545
|
const [firstChildren] = node.children;
|
|
2598
|
-
if (allowExpressions && node.children.length === 1 &&
|
|
2546
|
+
if (allowExpressions && node.children.length === 1 && JSX7.isLiteral(firstChildren) && !isChildren) return;
|
|
2599
2547
|
if (!allowExpressions && isChildren) {
|
|
2600
2548
|
return context.report({ messageId: "noUselessFragment", node });
|
|
2601
2549
|
} else if (!allowExpressions && !isChildren && node.children.length === 1) {
|
|
2602
2550
|
return context.report({ messageId: "noUselessFragment", node });
|
|
2603
2551
|
}
|
|
2604
|
-
const nonPaddingChildren = node.children.filter((child) => !
|
|
2552
|
+
const nonPaddingChildren = node.children.filter((child) => !JSX7.isPaddingSpaces(child));
|
|
2605
2553
|
if (nonPaddingChildren.length > 1) return;
|
|
2606
2554
|
if (nonPaddingChildren.length === 0) return context.report({ messageId: "noUselessFragment", node });
|
|
2607
2555
|
const [first] = nonPaddingChildren;
|
|
@@ -2843,7 +2791,7 @@ var prefer_shorthand_boolean_default = createRule({
|
|
|
2843
2791
|
create(context) {
|
|
2844
2792
|
function getReportDescriptor(node) {
|
|
2845
2793
|
const { value } = node;
|
|
2846
|
-
const propName =
|
|
2794
|
+
const propName = JSX7.getPropName(node);
|
|
2847
2795
|
const hasValueTrue = value?.type === AST_NODE_TYPES.JSXExpressionContainer && value.expression.type === AST_NODE_TYPES.Literal && value.expression.value === true;
|
|
2848
2796
|
if (!hasValueTrue) return O.none();
|
|
2849
2797
|
return O.some({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-x",
|
|
3
|
-
"version": "1.22.2-beta.
|
|
3
|
+
"version": "1.22.2-beta.7",
|
|
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",
|
|
@@ -49,13 +49,13 @@
|
|
|
49
49
|
"string-ts": "^2.2.0",
|
|
50
50
|
"ts-api-utils": "^2.0.0",
|
|
51
51
|
"ts-pattern": "^5.6.0",
|
|
52
|
-
"@eslint-react/
|
|
53
|
-
"@eslint-react/
|
|
54
|
-
"@eslint-react/
|
|
55
|
-
"@eslint-react/jsx": "1.22.2-beta.
|
|
56
|
-
"@eslint-react/types": "1.22.2-beta.
|
|
57
|
-
"@eslint-react/
|
|
58
|
-
"@eslint-react/
|
|
52
|
+
"@eslint-react/ast": "1.22.2-beta.7",
|
|
53
|
+
"@eslint-react/eff": "1.22.2-beta.7",
|
|
54
|
+
"@eslint-react/core": "1.22.2-beta.7",
|
|
55
|
+
"@eslint-react/jsx": "1.22.2-beta.7",
|
|
56
|
+
"@eslint-react/types": "1.22.2-beta.7",
|
|
57
|
+
"@eslint-react/shared": "1.22.2-beta.7",
|
|
58
|
+
"@eslint-react/var": "1.22.2-beta.7"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/react": "^19.0.2",
|