Skip to content

Commit 4609a3a

Browse files
committed
feat(plugins/react-x): add jsx-uses-vars
1 parent 01cc707 commit 4609a3a

File tree

7 files changed

+241
-98
lines changed

7 files changed

+241
-98
lines changed

package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@
4949
"devDependencies": {
5050
"@changesets/cli": "^2.27.9",
5151
"@effect/language-service": "^0.2.0",
52-
"@effect/platform": "^0.69.9",
53-
"@effect/platform-bun": "^0.49.10",
54-
"@effect/platform-node": "^0.64.10",
52+
"@effect/platform": "^0.69.10",
53+
"@effect/platform-bun": "^0.49.11",
54+
"@effect/platform-node": "^0.64.11",
5555
"@effect/schema": "^0.75.5",
5656
"@eslint/config-inspector": "^0.5.5",
5757
"@eslint/js": "^9.13.0",
@@ -71,7 +71,7 @@
7171
"concurrently": "^9.0.1",
7272
"cspell": "^8.15.4",
7373
"dprint": "^0.47.5",
74-
"effect": "^3.10.4",
74+
"effect": "^3.10.5",
7575
"esbuild": "^0.24.0",
7676
"eslint": "^9.13.0",
7777
"eslint-config-flat-gitignore": "^0.3.0",
@@ -87,7 +87,7 @@
8787
"eslint-plugin-unicorn": "^56.0.0",
8888
"eslint-plugin-vitest": "^0.5.4",
8989
"importx": "^0.5.0",
90-
"lefthook": "^1.8.1",
90+
"lefthook": "^1.8.2",
9191
"markdownlint": "^0.36.1",
9292
"publint": "^0.2.12",
9393
"react": "^18.3.1",

packages/plugins/eslint-plugin-react-x/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { name, version } from "../package.json";
55
import avoidShorthandBoolean from "./rules/avoid-shorthand-boolean";
66
import avoidShorthandFragment from "./rules/avoid-shorthand-fragment";
77
import forwardRefUsingRef from "./rules/ensure-forward-ref-using-ref";
8+
import jsxUsesVars from "./rules/jsx-uses-vars";
89
import noAccessStateInSetstate from "./rules/no-access-state-in-setstate";
910
import noArrayIndexKey from "./rules/no-array-index-key";
1011
import noChildrenCount from "./rules/no-children-count";
@@ -70,6 +71,7 @@ export default {
7071
"avoid-shorthand-boolean": avoidShorthandBoolean,
7172
"avoid-shorthand-fragment": avoidShorthandFragment,
7273
"ensure-forward-ref-using-ref": forwardRefUsingRef,
74+
"jsx-uses-vars": jsxUsesVars,
7375
"no-access-state-in-setstate": noAccessStateInSetstate,
7476
"no-array-index-key": noArrayIndexKey,
7577
"no-children-count": noChildrenCount,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { allValid, ruleTester } from "../../../../../test";
2+
import rule, { RULE_NAME } from "./jsx-uses-vars";
3+
4+
ruleTester.run(RULE_NAME, rule, {
5+
invalid: [],
6+
valid: [
7+
...allValid,
8+
{
9+
code: /* tsx */ `
10+
function foo() {
11+
var App;
12+
var bar = React.render(<App/>);
13+
return bar;
14+
};
15+
foo()
16+
`,
17+
},
18+
{
19+
code: /* tsx */ `
20+
var App;
21+
React.render(<App/>);
22+
`,
23+
},
24+
{
25+
code: /* tsx */ `
26+
var a = 1;
27+
React.render(<img src={a} />);
28+
`,
29+
},
30+
{
31+
code: /* tsx */ `
32+
var App;
33+
function f() {
34+
return <App />;
35+
}
36+
f();
37+
`,
38+
},
39+
{
40+
code: /* tsx */ `
41+
var App;
42+
<App.Hello />
43+
`,
44+
},
45+
{
46+
code: /* tsx */ `
47+
class HelloMessage {};
48+
<HelloMessage />
49+
`,
50+
},
51+
{
52+
code: /* tsx */ `
53+
class HelloMessage {
54+
render() {
55+
var HelloMessage = <div>Hello</div>;
56+
return HelloMessage;
57+
}
58+
};
59+
<HelloMessage />
60+
`,
61+
},
62+
{
63+
code: /* tsx */ `
64+
function foo() {
65+
var App = { Foo: { Bar: {} } };
66+
var bar = React.render(<App.Foo.Bar/>);
67+
return bar;
68+
};
69+
foo()
70+
`,
71+
},
72+
{
73+
code: /* tsx */ `
74+
function foo() {
75+
var App = { Foo: { Bar: { Baz: {} } } };
76+
var bar = React.render(<App.Foo.Bar.Baz/>);
77+
return bar;
78+
};
79+
foo()
80+
`,
81+
},
82+
{
83+
code: /* tsx */ `
84+
var object;
85+
React.render(<object.Tag />);
86+
`,
87+
},
88+
{
89+
code: /* tsx */ `
90+
var object;
91+
React.render(<object.tag />);
92+
`,
93+
},
94+
],
95+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { O } from "@eslint-react/tools";
2+
import type { TSESTree } from "@typescript-eslint/types";
3+
import { AST_NODE_TYPES } from "@typescript-eslint/types";
4+
import type { CamelCase } from "string-ts";
5+
6+
import { createRule } from "../utils";
7+
8+
export const RULE_NAME = "jsx-uses-vars";
9+
10+
export type MessageID = CamelCase<typeof RULE_NAME>;
11+
12+
export default createRule<[], MessageID>({
13+
meta: {
14+
type: "problem",
15+
docs: {
16+
// eslint-disable-next-line eslint-plugin/require-meta-docs-description
17+
description: "a helper rule to mark variables as used",
18+
},
19+
messages: {
20+
jsxUsesVars: "",
21+
},
22+
schema: [],
23+
},
24+
name: RULE_NAME,
25+
create(context) {
26+
function getName(node: TSESTree.Node): O.Option<string> {
27+
switch (node.type) {
28+
case AST_NODE_TYPES.JSXIdentifier:
29+
return O.some(node.name);
30+
case AST_NODE_TYPES.JSXMemberExpression:
31+
return getName(node.object);
32+
default:
33+
return O.none();
34+
}
35+
}
36+
return {
37+
JSXOpeningElement(node) {
38+
if (node.name.type === AST_NODE_TYPES.JSXIdentifier && /^[a-z]/u.test(node.name.name)) return;
39+
O.map(getName(node.name), (name) => {
40+
context.sourceCode.markVariableAsUsed(name, node);
41+
});
42+
},
43+
};
44+
},
45+
defaultOptions: [],
46+
});

packages/tools/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"publish": "pnpm run build && pnpm run lint:publish"
4343
},
4444
"devDependencies": {
45-
"effect": "^3.10.4",
45+
"effect": "^3.10.5",
4646
"tsup": "^8.3.5"
4747
}
4848
}

0 commit comments

Comments
 (0)