Skip to content

Commit ad90761

Browse files
Update: add enforceForJSX option to no-unused-expressions rule (#14012)
* Update: no-unused-expression flags unused JSX React's createElement call is side-effect free, as are most JSX pragmas. An unused JSX element indicates a logic error in the same way any unused, side-effect free expression is. This extension the no-unused-expression rule flags unused JSX elements unless the (new) allowJsx configuration option is set * fixup! Update: no-unused-expression flags unused JSX React's createElement call is side-effect free, as are most JSX pragmas. An unused JSX element indicates a logic error in the same way any unused, side-effect free expression is. This extension the no-unused-expression rule flags unused JSX elements when the (new) ignoreJSX configuration option is set * fixup! Update: no-unused-expression flags unused JSX * fixup! Update: no-unused-expression flags unused JSX * fixup! Update: no-unused-expression flags unused JSX * fixup! Update: no-unused-expression flags unused JSX * fixup! Update: no-unused-expression flags unused JSX * fixup! Update: no-unused-expression flags unused JSX * fixup! Update: no-unused-expression flags unused JSX * fixup! Update: no-unused-expression flags unused JSX * fixup! Update: no-unused-expression flags unused JSX Apply suggestions from code review Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com> Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>
1 parent d6c84af commit ad90761

File tree

3 files changed

+75
-1
lines changed

3 files changed

+75
-1
lines changed

docs/rules/no-unused-expressions.md

+25
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ This rule, in its default state, does not require any arguments. If you would li
3131
* `allowShortCircuit` set to `true` will allow you to use short circuit evaluations in your expressions (Default: `false`).
3232
* `allowTernary` set to `true` will enable you to use ternary operators in your expressions similarly to short circuit evaluations (Default: `false`).
3333
* `allowTaggedTemplates` set to `true` will enable you to use tagged template literals in your expressions (Default: `false`).
34+
* `enforceForJSX` set to `true` will flag unused JSX element expressions (Default: `false`).
3435

3536
These options allow unused expressions *only if all* of the code paths either directly change the state (for example, assignment statement) or could have *side effects* (for example, function call).
3637

@@ -161,3 +162,27 @@ Examples of **correct** code for the `{ "allowTaggedTemplates": true }` option:
161162

162163
tag`some tagged template string`;
163164
```
165+
166+
### enforceForJSX
167+
168+
JSX is most-commonly used in the React ecosystem, where it is compiled to `React.createElement` expressions. Though free from side-effects, these calls are not automatically flagged by the `no-unused-expression` rule. If you're using React, or any other side-effect-free JSX pragma, this option can be enabled to flag these expressions.
169+
170+
Examples of **incorrect** code for the `{ "enforceForJSX": true }` option:
171+
172+
```jsx
173+
/*eslint no-unused-expressions: ["error", { "enforceForJSX": true }]*/
174+
175+
<MyComponent />;
176+
177+
<></>;
178+
```
179+
180+
Examples of **correct** code for the `{ "enforceForJSX": true }` option:
181+
182+
```jsx
183+
/*eslint no-unused-expressions: ["error", { "enforceForJSX": true }]*/
184+
185+
var myComponentPartial = <MyComponent />;
186+
187+
var myFragment = <></>;
188+
```

lib/rules/no-unused-expressions.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ module.exports = {
5050
allowTaggedTemplates: {
5151
type: "boolean",
5252
default: false
53+
},
54+
enforceForJSX: {
55+
type: "boolean",
56+
default: false
5357
}
5458
},
5559
additionalProperties: false
@@ -65,7 +69,8 @@ module.exports = {
6569
const config = context.options[0] || {},
6670
allowShortCircuit = config.allowShortCircuit || false,
6771
allowTernary = config.allowTernary || false,
68-
allowTaggedTemplates = config.allowTaggedTemplates || false;
72+
allowTaggedTemplates = config.allowTaggedTemplates || false,
73+
enforceForJSX = config.enforceForJSX || false;
6974

7075
// eslint-disable-next-line jsdoc/require-description
7176
/**
@@ -140,6 +145,12 @@ module.exports = {
140145
},
141146
FunctionExpression: alwaysTrue,
142147
Identifier: alwaysTrue,
148+
JSXElement() {
149+
return enforceForJSX;
150+
},
151+
JSXFragment() {
152+
return enforceForJSX;
153+
},
143154
Literal: alwaysTrue,
144155
LogicalExpression(node) {
145156
if (allowShortCircuit) {

tests/lib/rules/no-unused-expressions.js

+38
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,30 @@ ruleTester.run("no-unused-expressions", rule, {
8282
{
8383
code: "obj?.foo(\"bar\")",
8484
parserOptions: { ecmaVersion: 11 }
85+
},
86+
87+
// JSX
88+
{
89+
code: "<div />",
90+
parserOptions: { ecmaFeatures: { jsx: true } }
91+
},
92+
{
93+
code: "<></>",
94+
parserOptions: { ecmaFeatures: { jsx: true } }
95+
},
96+
{
97+
code: "var partial = <div />",
98+
parserOptions: { ecmaFeatures: { jsx: true } }
99+
},
100+
{
101+
code: "var partial = <div />",
102+
options: [{ enforceForJSX: true }],
103+
parserOptions: { ecmaFeatures: { jsx: true } }
104+
},
105+
{
106+
code: "var partial = <></>",
107+
options: [{ enforceForJSX: true }],
108+
parserOptions: { ecmaFeatures: { jsx: true } }
85109
}
86110
],
87111
invalid: [
@@ -152,6 +176,20 @@ ruleTester.run("no-unused-expressions", rule, {
152176
code: "obj?.foo().bar",
153177
parserOptions: { ecmaVersion: 2020 },
154178
errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
179+
},
180+
181+
// JSX
182+
{
183+
code: "<div />",
184+
options: [{ enforceForJSX: true }],
185+
parserOptions: { ecmaFeatures: { jsx: true } },
186+
errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
187+
},
188+
{
189+
code: "<></>",
190+
options: [{ enforceForJSX: true }],
191+
parserOptions: { ecmaFeatures: { jsx: true } },
192+
errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
155193
}
156194
]
157195
});

0 commit comments

Comments
 (0)