Skip to content

Commit 0b0fdfd

Browse files
authored
refactor: 'no-duplicate-key' and type expression utils (#891)
1 parent 23c17ad commit 0b0fdfd

19 files changed

+365
-175
lines changed

packages/plugins/eslint-plugin-react-debug/src/rules/function-component.spec.ts

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,6 +1366,62 @@ ruleTester.run(RULE_NAME, rule, {
13661366
},
13671367
],
13681368
},
1369+
{
1370+
code: /* tsx */ `
1371+
const MyComponent1 = (() => null)!;
1372+
const MyComponent2 = (() => null)!!;
1373+
const MyComponent3 = (() => null)!!! as A;
1374+
const MyComponent4 = (() => null)!!! satisfies A;
1375+
const MyComponent5 = (() => null)!!! as A satisfies B;
1376+
`,
1377+
errors: [
1378+
{
1379+
messageId: "functionComponent",
1380+
data: {
1381+
name: "MyComponent1",
1382+
forwardRef: false,
1383+
hookCalls: 0,
1384+
memo: false,
1385+
},
1386+
},
1387+
{
1388+
messageId: "functionComponent",
1389+
data: {
1390+
name: "MyComponent2",
1391+
forwardRef: false,
1392+
hookCalls: 0,
1393+
memo: false,
1394+
},
1395+
},
1396+
{
1397+
messageId: "functionComponent",
1398+
data: {
1399+
name: "MyComponent3",
1400+
forwardRef: false,
1401+
hookCalls: 0,
1402+
memo: false,
1403+
},
1404+
},
1405+
{
1406+
messageId: "functionComponent",
1407+
data: {
1408+
name: "MyComponent4",
1409+
forwardRef: false,
1410+
hookCalls: 0,
1411+
memo: false,
1412+
},
1413+
},
1414+
{
1415+
messageId: "functionComponent",
1416+
data: {
1417+
name: "MyComponent5",
1418+
forwardRef: false,
1419+
hookCalls: 0,
1420+
memo: false,
1421+
},
1422+
},
1423+
],
1424+
},
13691425
],
13701426
valid: [
13711427
...allFunctions,
@@ -1375,25 +1431,21 @@ ruleTester.run(RULE_NAME, rule, {
13751431
"const results = allSettled.mapLike((x) => (x.status === 'fulfilled' ? format(x.value) : null))",
13761432
/* tsx */ `
13771433
export const action = (() => {
1378-
// ^?
13791434
return null;
13801435
});
13811436
`,
13821437
/* tsx */ `
13831438
export const action = (() => {
1384-
// ^?
13851439
return null;
13861440
}) as ActionFUnction;
13871441
`,
13881442
/* tsx */ `
13891443
export const action = (() => {
1390-
// ^?
13911444
return null;
13921445
}) satisfies ActionFUnction;
13931446
`,
13941447
/* tsx */ `
13951448
export const action = (() => {
1396-
// ^?
13971449
return null;
13981450
}) as ActionFUnction satisfies ActionFUnction;
13991451
`,

packages/plugins/eslint-plugin-react-x/src/rules/no-access-state-in-setstate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export const RULE_FEATURES = [
1717
export type MessageID = CamelCase<typeof RULE_NAME>;
1818

1919
function getName(node: TSESTree.Expression | TSESTree.PrivateIdentifier): O.Option<string> {
20-
if (node.type === AST_NODE_TYPES.TSAsExpression) {
20+
if (AST.isTypeExpression(node)) {
2121
return getName(node.expression);
2222
}
2323
if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) {

packages/plugins/eslint-plugin-react-x/src/rules/no-direct-mutation-state.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const RULE_FEATURES = [
1818
export type MessageID = CamelCase<typeof RULE_NAME>;
1919

2020
function getName(node: TSESTree.Expression | TSESTree.PrivateIdentifier): O.Option<string> {
21-
if (node.type === AST_NODE_TYPES.TSAsExpression) {
21+
if (AST.isTypeExpression(node)) {
2222
return getName(node.expression);
2323
}
2424
if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) {

packages/plugins/eslint-plugin-react-x/src/rules/no-duplicate-key.spec.ts

Lines changed: 133 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,19 @@ ruleTester.run(RULE_NAME, rule, {
1717
{
1818
messageId: "noDuplicateKey",
1919
data: {
20-
value: '"1"',
20+
value: 'key="1"',
2121
},
2222
},
2323
{
2424
messageId: "noDuplicateKey",
2525
data: {
26-
value: '"1"',
26+
value: 'key="1"',
2727
},
2828
},
2929
{
3030
messageId: "noDuplicateKey",
3131
data: {
32-
value: '"1"',
32+
value: 'key="1"',
3333
},
3434
},
3535
],
@@ -48,19 +48,19 @@ ruleTester.run(RULE_NAME, rule, {
4848
{
4949
messageId: "noDuplicateKey",
5050
data: {
51-
value: '"1"',
51+
value: 'key="1"',
5252
},
5353
},
5454
{
5555
messageId: "noDuplicateKey",
5656
data: {
57-
value: '"1"',
57+
value: 'key="1"',
5858
},
5959
},
6060
{
6161
messageId: "noDuplicateKey",
6262
data: {
63-
value: '"1"',
63+
value: 'key="1"',
6464
},
6565
},
6666
],
@@ -75,7 +75,126 @@ ruleTester.run(RULE_NAME, rule, {
7575
{
7676
messageId: "noDuplicateKey",
7777
data: {
78-
value: '"1"',
78+
value: 'key="1"',
79+
},
80+
},
81+
],
82+
},
83+
{
84+
code: /* tsx */ `
85+
const App = () => {
86+
return [1, 2, 3].map((item) => { return <div key="1">{item}</div> })
87+
};
88+
`,
89+
errors: [
90+
{
91+
messageId: "noDuplicateKey",
92+
data: {
93+
value: 'key="1"',
94+
},
95+
},
96+
],
97+
},
98+
{
99+
code: /* tsx */ `
100+
const App = () => {
101+
return nested.map((item) => {
102+
return <div key="1">{item.map((i) => <div key="a">{i}</div>)}</div>
103+
})
104+
};
105+
`,
106+
errors: [
107+
{
108+
messageId: "noDuplicateKey",
109+
data: {
110+
value: 'key="1"',
111+
},
112+
},
113+
{
114+
messageId: "noDuplicateKey",
115+
data: {
116+
value: 'key="a"',
117+
},
118+
},
119+
],
120+
},
121+
{
122+
code: /* tsx */ `
123+
const App = () => {
124+
return nested.map((foo) => {
125+
return <div key="foo">{foo.map((bar) => <div key="bar">{bar.map((baz) => <div key="baz">{baz}</div>)}</div>)}</div>
126+
})
127+
};
128+
`,
129+
errors: [
130+
{
131+
messageId: "noDuplicateKey",
132+
data: {
133+
value: 'key="foo"',
134+
},
135+
},
136+
{
137+
messageId: "noDuplicateKey",
138+
data: {
139+
value: 'key="bar"',
140+
},
141+
},
142+
{
143+
messageId: "noDuplicateKey",
144+
data: {
145+
value: 'key="baz"',
146+
},
147+
},
148+
],
149+
},
150+
{
151+
code: /* tsx */ `
152+
const App = () => {
153+
return nested?.map((foo) => {
154+
return <div key="foo">{foo!.map((bar) => <div key="bar">{bar!!.map(((baz) => <div key="baz">{baz}</div>)!!! as A satisfies B)}</div>)}</div>
155+
})
156+
};
157+
`,
158+
errors: [
159+
{
160+
messageId: "noDuplicateKey",
161+
data: {
162+
value: 'key="foo"',
163+
},
164+
},
165+
{
166+
messageId: "noDuplicateKey",
167+
data: {
168+
value: 'key="bar"',
169+
},
170+
},
171+
{
172+
messageId: "noDuplicateKey",
173+
data: {
174+
value: 'key="baz"',
175+
},
176+
},
177+
],
178+
},
179+
{
180+
code: /* tsx */ `
181+
const App = () => {
182+
return nested.map((foo) => {
183+
return <div key="foo">{foo.notmap((bar) => <div key="bar">{bar.map((baz) => <div key="baz">{baz}</div>)}</div>)}</div>
184+
})
185+
};
186+
`,
187+
errors: [
188+
{
189+
messageId: "noDuplicateKey",
190+
data: {
191+
value: 'key="foo"',
192+
},
193+
},
194+
{
195+
messageId: "noDuplicateKey",
196+
data: {
197+
value: 'key="baz"',
79198
},
80199
},
81200
],
@@ -102,5 +221,12 @@ ruleTester.run(RULE_NAME, rule, {
102221
return [1, 2, 3].map((item) => { const key = item; return <div key={key}>{item}</div> })
103222
};
104223
`,
224+
/* tsx */ `
225+
const App = () => {
226+
return nested.map((item) => {
227+
return <div key={item}>{item.map((i) => { return <div key={i}>{i}</div> })}</div>
228+
})
229+
};
230+
`,
105231
],
106232
});

0 commit comments

Comments
 (0)