Skip to content

Commit

Permalink
feat(plugins/react-x): add jsx-uses-vars, closes #834 (#845)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rel1cx authored Oct 30, 2024
1 parent 01cc707 commit c8517d6
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 102 deletions.
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@
"devDependencies": {
"@changesets/cli": "^2.27.9",
"@effect/language-service": "^0.2.0",
"@effect/platform": "^0.69.9",
"@effect/platform-bun": "^0.49.10",
"@effect/platform-node": "^0.64.10",
"@effect/platform": "^0.69.10",
"@effect/platform-bun": "^0.49.11",
"@effect/platform-node": "^0.64.11",
"@effect/schema": "^0.75.5",
"@eslint/config-inspector": "^0.5.5",
"@eslint/js": "^9.13.0",
Expand All @@ -71,7 +71,7 @@
"concurrently": "^9.0.1",
"cspell": "^8.15.4",
"dprint": "^0.47.5",
"effect": "^3.10.4",
"effect": "^3.10.5",
"esbuild": "^0.24.0",
"eslint": "^9.13.0",
"eslint-config-flat-gitignore": "^0.3.0",
Expand All @@ -87,7 +87,7 @@
"eslint-plugin-unicorn": "^56.0.0",
"eslint-plugin-vitest": "^0.5.4",
"importx": "^0.5.0",
"lefthook": "^1.8.1",
"lefthook": "^1.8.2",
"markdownlint": "^0.36.1",
"publint": "^0.2.12",
"react": "^18.3.1",
Expand Down
2 changes: 2 additions & 0 deletions packages/plugins/eslint-plugin-react-x/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default [
rules: {
// react-x recommended rules
"react-x/ensure-forward-ref-using-ref": "warn",
"react-x/jsx-uses-vars": "warn",
"react-x/no-access-state-in-setstate": "error",
"react-x/no-array-index-key": "warn",
"react-x/no-children-count": "warn",
Expand Down Expand Up @@ -74,6 +75,7 @@ export default [
| `avoid-shorthand-boolean` | Prevents using shorthand syntax for boolean attributes. | 🎨 | | |
| `avoid-shorthand-fragment` | Prevents using shorthand syntax for fragments. | 🎨 | | |
| `ensure-forward-ref-using-ref` | Requires that components wrapped with `forwardRef` must have a `ref` parameter. | ✔️ | | |
| `jsx-uses-vars | Prevents variables used in JSX to be marked as unused. | ✔️ | | |
| `no-access-state-in-setstate` | Prevents accessing `this.state` inside `setState` calls. | ✔️ | | |
| `no-array-index-key` | Prevents using array `index` as `key`. | 🧐 | | |
| `no-children-count` | Prevents using `Children.count`. || | |
Expand Down
2 changes: 2 additions & 0 deletions packages/plugins/eslint-plugin-react-x/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { name, version } from "../package.json";
import avoidShorthandBoolean from "./rules/avoid-shorthand-boolean";
import avoidShorthandFragment from "./rules/avoid-shorthand-fragment";
import forwardRefUsingRef from "./rules/ensure-forward-ref-using-ref";
import jsxUsesVars from "./rules/jsx-uses-vars";
import noAccessStateInSetstate from "./rules/no-access-state-in-setstate";
import noArrayIndexKey from "./rules/no-array-index-key";
import noChildrenCount from "./rules/no-children-count";
Expand Down Expand Up @@ -70,6 +71,7 @@ export default {
"avoid-shorthand-boolean": avoidShorthandBoolean,
"avoid-shorthand-fragment": avoidShorthandFragment,
"ensure-forward-ref-using-ref": forwardRefUsingRef,
"jsx-uses-vars": jsxUsesVars,
"no-access-state-in-setstate": noAccessStateInSetstate,
"no-array-index-key": noArrayIndexKey,
"no-children-count": noChildrenCount,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { allValid, ruleTester } from "../../../../../test";
import rule, { RULE_NAME } from "./jsx-uses-vars";

ruleTester.run(RULE_NAME, rule, {
invalid: [],
valid: [
...allValid,
{
code: /* tsx */ `
function foo() {
var App;
var bar = React.render(<App/>);
return bar;
};
foo()
`,
},
{
code: /* tsx */ `
var App;
React.render(<App/>);
`,
},
{
code: /* tsx */ `
var a = 1;
React.render(<img src={a} />);
`,
},
{
code: /* tsx */ `
var App;
function f() {
return <App />;
}
f();
`,
},
{
code: /* tsx */ `
var App;
<App.Hello />
`,
},
{
code: /* tsx */ `
class HelloMessage {};
<HelloMessage />
`,
},
{
code: /* tsx */ `
class HelloMessage {
render() {
var HelloMessage = <div>Hello</div>;
return HelloMessage;
}
};
<HelloMessage />
`,
},
{
code: /* tsx */ `
function foo() {
var App = { Foo: { Bar: {} } };
var bar = React.render(<App.Foo.Bar/>);
return bar;
};
foo()
`,
},
{
code: /* tsx */ `
function foo() {
var App = { Foo: { Bar: { Baz: {} } } };
var bar = React.render(<App.Foo.Bar.Baz/>);
return bar;
};
foo()
`,
},
{
code: /* tsx */ `
var object;
React.render(<object.Tag />);
`,
},
{
code: /* tsx */ `
var object;
React.render(<object.tag />);
`,
},
],
});
46 changes: 46 additions & 0 deletions packages/plugins/eslint-plugin-react-x/src/rules/jsx-uses-vars.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { O } from "@eslint-react/tools";
import type { TSESTree } from "@typescript-eslint/types";
import { AST_NODE_TYPES } from "@typescript-eslint/types";
import type { CamelCase } from "string-ts";

import { createRule } from "../utils";

export const RULE_NAME = "jsx-uses-vars";

export type MessageID = CamelCase<typeof RULE_NAME>;

export default createRule<[], MessageID>({
meta: {
type: "problem",
docs: {
// eslint-disable-next-line eslint-plugin/require-meta-docs-description
description: "a helper rule to mark variables as used",
},
messages: {
jsxUsesVars: "",
},
schema: [],
},
name: RULE_NAME,
create(context) {
function getName(node: TSESTree.Node): O.Option<string> {
switch (node.type) {
case AST_NODE_TYPES.JSXIdentifier:
return O.some(node.name);
case AST_NODE_TYPES.JSXMemberExpression:
return getName(node.object);
default:
return O.none();
}
}
return {
JSXOpeningElement(node) {
if (node.name.type === AST_NODE_TYPES.JSXIdentifier && /^[a-z]/u.test(node.name.name)) return;
O.map(getName(node.name), (name) => {
context.sourceCode.markVariableAsUsed(name, node);
});
},
};
},
defaultOptions: [],
});
9 changes: 5 additions & 4 deletions packages/plugins/eslint-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import { padKeysLeft } from "./utils";

const allPreset = {
// Part: Core
"avoid-shorthand-boolean": "warn",
"avoid-shorthand-fragment": "warn",
"ensure-forward-ref-using-ref": "warn",
"jsx-uses-vars": "warn",
"no-access-state-in-setstate": "error",
"no-array-index-key": "warn",
"no-children-count": "warn",
Expand Down Expand Up @@ -58,9 +61,6 @@ const allPreset = {
// "prefer-read-only-props": "warn", // This rule requires type information
"prefer-shorthand-boolean": "warn",
"prefer-shorthand-fragment": "warn",
// eslint-disable-next-line perfectionist/sort-objects
"avoid-shorthand-boolean": "warn",
"avoid-shorthand-fragment": "warn",

// Part: DOM
"dom/no-children-in-void-dom-elements": "warn",
Expand Down Expand Up @@ -96,9 +96,10 @@ const allPreset = {
} as const satisfies RulePreset;

const corePreset = {
"ensure-forward-ref-using-ref": "warn",
// "avoid-shorthand-boolean": "warn",
// "avoid-shorthand-fragment": "warn",
"ensure-forward-ref-using-ref": "warn",
"jsx-uses-vars": "warn",
"no-access-state-in-setstate": "error",
"no-array-index-key": "warn",
"no-children-count": "warn",
Expand Down
2 changes: 1 addition & 1 deletion packages/tools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"publish": "pnpm run build && pnpm run lint:publish"
},
"devDependencies": {
"effect": "^3.10.4",
"effect": "^3.10.5",
"tsup": "^8.3.5"
}
}
Loading

0 comments on commit c8517d6

Please sign in to comment.