Skip to content

Commit c7a11de

Browse files
authored
fix: refactor JSX runtime annotation handling (#1038)
1 parent 37b9905 commit c7a11de

File tree

20 files changed

+209
-87
lines changed

20 files changed

+209
-87
lines changed

apps/website/content/docs/rules/overview.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Linter rules can have false positives, false negatives, and some rules are depen
2727
| :----------------------------------------------------------------------------------- | :- | :------: | :---------------------------------------------------------------------------------------------------- | :-----: |
2828
| [`jsx-no-duplicate-props`](./jsx-no-duplicate-props) | 1️⃣ | | Disallow duplicate props in JSX elements | |
2929
| [`jsx-no-undef`](./jsx-no-undef) | 0️⃣ | | Disallow undefined variables in JSX elements | |
30-
| [`jsx-uses-react`](./jsx-uses-react) | 1️⃣ | | Marks React variables as used when JSX is used in the file | |
30+
| [`jsx-uses-react`](./jsx-uses-react) | 1️⃣ | | Marks React variables as used when JSX is used | |
3131
| [`jsx-uses-vars`](./jsx-uses-vars) | 1️⃣ | | Marks variables used in JSX elements as used | |
3232
| [`no-access-state-in-setstate`](./no-access-state-in-setstate) | 2️⃣ | | Disallow accessing `this.state` inside `setState` calls | |
3333
| [`no-array-index-key`](./no-array-index-key) | 1️⃣ | | Disallow an item's index in the array as its key | |

packages/plugins/eslint-plugin-react-x/src/rules/jsx-uses-react.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ react-x/jsx-uses-react
2121

2222
## Description
2323

24-
Marks React variables as used when JSX is used in the file.
24+
Marks React variables as used when JSX is used.
2525

2626
If you are using the `@jsx` pragma this rule will mark the designated variable and not the React one.
2727

packages/plugins/eslint-plugin-react-x/src/rules/jsx-uses-react.spec.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ debug
2929
console.log(Hello);
3030
`,
3131
errors: [
32-
{
33-
messageId: "jsxUsesReact",
34-
data: { name: "React" },
35-
},
3632
{
3733
messageId: "jsxUsesReact",
3834
data: { name: "React.createElement" },

packages/plugins/eslint-plugin-react-x/src/rules/jsx-uses-react.ts

Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@ import type { TSESTree } from "@typescript-eslint/types";
22
import type { RuleListener } from "@typescript-eslint/utils/ts-eslint";
33

44
import type { CamelCase } from "string-ts";
5-
import {
6-
JsxRuntime,
7-
RE_JSX_ANNOTATION,
8-
RE_JSX_FRAG_ANNOTATION,
9-
type RuleContext,
10-
type RuleFeature,
11-
} from "@eslint-react/kit";
5+
import { JsxRuntime, type RuleContext, type RuleFeature } from "@eslint-react/kit";
126
import { JsxEmit } from "typescript";
137
import { createRule } from "../utils";
148

@@ -18,13 +12,13 @@ export const RULE_FEATURES = [] as const satisfies RuleFeature[];
1812

1913
export type MessageID = CamelCase<typeof RULE_NAME>;
2014

21-
export const debug = true;
15+
export const debug = false;
2216

2317
export default createRule<[], MessageID>({
2418
meta: {
2519
type: "problem",
2620
docs: {
27-
description: "Marks React variables as used when JSX is used in the file.",
21+
description: "Marks React variables as used when JSX is used.",
2822
[Symbol.for("rule_features")]: RULE_FEATURES,
2923
},
3024
messages: {
@@ -38,32 +32,24 @@ export default createRule<[], MessageID>({
3832
});
3933

4034
export function create(context: RuleContext<MessageID, []>): RuleListener {
41-
const { jsx, jsxFactory, jsxFragmentFactory, reactNamespace } = JsxRuntime.getJsxRuntimeOptionsFromContext(context);
42-
const jsxAnnotation = getJsxAnnotation(context);
35+
const jsxOptions = JsxRuntime.getJsxRuntimeOptions(context);
36+
const jsxAnnotation = JsxRuntime.getJsxRuntimeAnnotation(context);
37+
const jsx = jsxAnnotation.jsxRuntime === "classic"
38+
? JsxEmit.React
39+
: jsxOptions.jsx;
4340
if (jsx === JsxEmit.ReactJSX || jsx === JsxEmit.ReactJSXDev) return {};
4441

42+
const jsxFactory = jsxAnnotation.jsx ?? jsxOptions.jsxFactory;
43+
const jsxFragmentFactory = jsxAnnotation.jsxFrag ?? jsxOptions.jsxFragmentFactory;
44+
4545
function handleJsxElement(node: TSESTree.Node) {
46-
if (jsxAnnotation == null) {
47-
context.sourceCode.markVariableAsUsed(reactNamespace, node);
48-
context.sourceCode.markVariableAsUsed(jsxFactory, node);
49-
debugReport(context, node, reactNamespace);
50-
debugReport(context, node, jsxFactory);
51-
}
52-
if (jsxAnnotation?.jsx != null) {
53-
context.sourceCode.markVariableAsUsed(jsxAnnotation.jsx, node);
54-
debugReport(context, node, jsxAnnotation.jsx);
55-
}
46+
context.sourceCode.markVariableAsUsed(jsxFactory, node);
47+
debugReport(context, node, jsxFactory);
5648
}
5749

5850
function handleJsxFragment(node: TSESTree.Node) {
59-
if (jsxAnnotation == null) {
60-
context.sourceCode.markVariableAsUsed(jsxFragmentFactory, node);
61-
debugReport(context, node, jsxFragmentFactory);
62-
}
63-
if (jsxAnnotation?.jsxFrag != null) {
64-
context.sourceCode.markVariableAsUsed(jsxAnnotation.jsxFrag, node);
65-
debugReport(context, node, jsxAnnotation.jsxFrag);
66-
}
51+
context.sourceCode.markVariableAsUsed(jsxFragmentFactory, node);
52+
debugReport(context, node, jsxFragmentFactory);
6753
}
6854

6955
return {
@@ -73,19 +59,6 @@ export function create(context: RuleContext<MessageID, []>): RuleListener {
7359
};
7460
}
7561

76-
function getJsxAnnotation(context: RuleContext) {
77-
if (!context.sourceCode.text.includes("@jsx")) return;
78-
const allComments = context.sourceCode.getAllComments();
79-
const jsxComment = allComments.find((n) => RE_JSX_ANNOTATION.test(n.value));
80-
const jsxFragComment = allComments.find((n) => RE_JSX_FRAG_ANNOTATION.test(n.value));
81-
const jsx = jsxComment?.value.match(RE_JSX_ANNOTATION)?.[1];
82-
const jsxFrag = jsxFragComment?.value.match(RE_JSX_FRAG_ANNOTATION)?.[1];
83-
return {
84-
jsx,
85-
jsxFrag,
86-
};
87-
}
88-
8962
function debugReport(context: RuleContext, node: TSESTree.Node, name: string) {
9063
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
9164
if (!debug) return;

packages/utilities/kit/docs/@eslint-react/namespaces/JsxRuntime/README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,23 @@
66

77
# JsxRuntime
88

9+
## Interfaces
10+
11+
- [JsxRuntimeAnnotation](interfaces/JsxRuntimeAnnotation.md)
12+
913
## Type Aliases
1014

1115
- [JsxRuntimeOptions](type-aliases/JsxRuntimeOptions.md)
1216

17+
## Variables
18+
19+
- [RE\_JSX\_RT\_ANNOTATION\_JSX](variables/RE_JSX_RT_ANNOTATION_JSX.md)
20+
- [RE\_JSX\_RT\_ANNOTATION\_JSX\_FRAG](variables/RE_JSX_RT_ANNOTATION_JSX_FRAG.md)
21+
- [RE\_JSX\_RT\_ANNOTATION\_JSX\_IMPORT\_SOURCE](variables/RE_JSX_RT_ANNOTATION_JSX_IMPORT_SOURCE.md)
22+
- [RE\_JSX\_RT\_ANNOTATION\_JSX\_RUNTIME](variables/RE_JSX_RT_ANNOTATION_JSX_RUNTIME.md)
23+
1324
## Functions
1425

15-
- [getJsxRuntimeOptionsFromContext](functions/getJsxRuntimeOptionsFromContext.md)
26+
- [getJsxRuntimeAnnotation](functions/getJsxRuntimeAnnotation.md)
27+
- [getJsxRuntimeOptions](functions/getJsxRuntimeOptions.md)
28+
- [make](functions/make.md)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[**@eslint-react/kit**](../../../../README.md)
2+
3+
***
4+
5+
[@eslint-react/kit](../../../../README.md) / [JsxRuntime](../README.md) / getJsxRuntimeAnnotation
6+
7+
# Function: getJsxRuntimeAnnotation()
8+
9+
> **getJsxRuntimeAnnotation**(`context`): [`JsxRuntimeAnnotation`](../interfaces/JsxRuntimeAnnotation.md)
10+
11+
Get the a JsxRuntimeAnnotation object representing the JSX annotations in the file.
12+
13+
## Parameters
14+
15+
### context
16+
17+
[`RuleContext`](../../../../type-aliases/RuleContext.md)
18+
19+
The RuleContext
20+
21+
## Returns
22+
23+
[`JsxRuntimeAnnotation`](../interfaces/JsxRuntimeAnnotation.md)
24+
25+
JsxRuntimeAnnotation
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
***
44

5-
[@eslint-react/kit](../../../../README.md) / [JsxRuntime](../README.md) / getJsxRuntimeOptionsFromContext
5+
[@eslint-react/kit](../../../../README.md) / [JsxRuntime](../README.md) / getJsxRuntimeOptions
66

7-
# Function: getJsxRuntimeOptionsFromContext()
7+
# Function: getJsxRuntimeOptions()
88

9-
> **getJsxRuntimeOptionsFromContext**(`context`): `object`
9+
> **getJsxRuntimeOptions**(`context`): `object`
1010
1111
Get JsxRuntimeOptions from RuleContext
1212

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[**@eslint-react/kit**](../../../../README.md)
2+
3+
***
4+
5+
[@eslint-react/kit](../../../../README.md) / [JsxRuntime](../README.md) / make
6+
7+
# Function: make()
8+
9+
> **make**(): [`JsxRuntimeAnnotation`](../interfaces/JsxRuntimeAnnotation.md)
10+
11+
## Returns
12+
13+
[`JsxRuntimeAnnotation`](../interfaces/JsxRuntimeAnnotation.md)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[**@eslint-react/kit**](../../../../README.md)
2+
3+
***
4+
5+
[@eslint-react/kit](../../../../README.md) / [JsxRuntime](../README.md) / JsxRuntimeAnnotation
6+
7+
# Interface: JsxRuntimeAnnotation
8+
9+
## Properties
10+
11+
### jsx
12+
13+
> **jsx**: `undefined` \| `string`
14+
15+
***
16+
17+
### jsxFrag
18+
19+
> **jsxFrag**: `undefined` \| `string`
20+
21+
***
22+
23+
### jsxImportSource
24+
25+
> **jsxImportSource**: `undefined` \| `string`
26+
27+
***
28+
29+
### jsxRuntime
30+
31+
> **jsxRuntime**: `undefined` \| `string`
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[**@eslint-react/kit**](../../../../README.md)
2+
3+
***
4+
5+
[@eslint-react/kit](../../../../README.md) / [JsxRuntime](../README.md) / RE\_JSX\_RT\_ANNOTATION\_JSX
6+
7+
# Variable: RE\_JSX\_RT\_ANNOTATION\_JSX
8+
9+
> `const` **RE\_JSX\_RT\_ANNOTATION\_JSX**: [`RegExp`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp)
10+
11+
Regular expression for matching a `@jsx` annotation comment.

0 commit comments

Comments
 (0)