Skip to content

Commit 6cb0f00

Browse files
developer-bandiljharb
authored andcommitted
[Fix] jsx-boolean-value: make error messages clearer
1 parent 2124d13 commit 6cb0f00

File tree

3 files changed

+60
-40
lines changed

3 files changed

+60
-40
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
3030
* [`forbid-elements`]: prevent a crash on `createElement()` ([#3632][] @ljharb)
3131

3232
### Changed
33+
* [`jsx-boolean-value`]: make error messages clearer ([#3691][] @developer-bandi)
3334
* [Refactor] `propTypes`: extract type params to var ([#3634][] @HenryBrown0)
3435
* [Refactor] [`boolean-prop-naming`]: invert if statement ([#3634][] @HenryBrown0)
3536
* [Refactor] [`function-component-definition`]: exit early if no type params ([#3634][] @HenryBrown0)
@@ -40,6 +41,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
4041
* [Docs] [`hook-use-state`]: fix an undefined variable ([#3626][] @chentsulin)
4142

4243
[#3697]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3697
44+
[#3691]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3691
4345
[#3690]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3690
4446
[#3680]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3680
4547
[#3679]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3679

lib/rules/jsx-boolean-value.js

+9-28
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,6 @@ const exceptionsSchema = {
2121
const ALWAYS = 'always';
2222
const NEVER = 'never';
2323

24-
const errorData = new WeakMap();
25-
/**
26-
* @param {object} exceptions
27-
* @returns {object}
28-
*/
29-
function getErrorData(exceptions) {
30-
if (!errorData.has(exceptions)) {
31-
const exceptionProps = Array.from(exceptions, (name) => `\`${name}\``).join(', ');
32-
const exceptionsMessage = exceptions.size > 0 ? ` for the following props: ${exceptionProps}` : '';
33-
errorData.set(exceptions, { exceptionsMessage });
34-
}
35-
return errorData.get(exceptions);
36-
}
3724
/**
3825
* @param {string} configuration
3926
* @param {Set<string>} exceptions
@@ -62,12 +49,9 @@ function isNever(configuration, exceptions, propName) {
6249
}
6350

6451
const messages = {
65-
omitBoolean: 'Value must be omitted for boolean attributes{{exceptionsMessage}}',
66-
omitBoolean_noMessage: 'Value must be omitted for boolean attributes',
67-
setBoolean: 'Value must be set for boolean attributes{{exceptionsMessage}}',
68-
setBoolean_noMessage: 'Value must be set for boolean attributes',
69-
omitPropAndBoolean: 'Value and Prop must be omitted for false attributes{{exceptionsMessage}}',
70-
omitPropAndBoolean_noMessage: 'Value and Prop must be omitted for false attributes',
52+
omitBoolean: 'Value must be omitted for boolean attribute `{{propName}}`',
53+
setBoolean: 'Value must be set for boolean attribute `{{propName}}`',
54+
omitPropAndBoolean: 'Value must be omitted for `false` attribute: `{{propName}}`',
7155
};
7256

7357
module.exports = {
@@ -135,8 +119,8 @@ module.exports = {
135119
isAlways(configuration, exceptions, propName)
136120
&& value === null
137121
) {
138-
const data = getErrorData(exceptions);
139-
const messageId = data.exceptionsMessage ? 'setBoolean' : 'setBoolean_noMessage';
122+
const messageId = 'setBoolean';
123+
const data = { propName };
140124
report(context, messages[messageId], messageId, {
141125
node,
142126
data,
@@ -152,8 +136,8 @@ module.exports = {
152136
&& value.type === 'JSXExpressionContainer'
153137
&& value.expression.value === true
154138
) {
155-
const data = getErrorData(exceptions);
156-
const messageId = data.exceptionsMessage ? 'omitBoolean' : 'omitBoolean_noMessage';
139+
const messageId = 'omitBoolean';
140+
const data = { propName };
157141
report(context, messages[messageId], messageId, {
158142
node,
159143
data,
@@ -169,11 +153,8 @@ module.exports = {
169153
&& value.type === 'JSXExpressionContainer'
170154
&& value.expression.value === false
171155
) {
172-
const data = getErrorData(exceptions);
173-
const messageId = data.exceptionsMessage
174-
? 'omitPropAndBoolean'
175-
: 'omitPropAndBoolean_noMessage';
176-
156+
const messageId = 'omitPropAndBoolean';
157+
const data = { propName };
177158
report(context, messages[messageId], messageId, {
178159
node,
179160
data,

tests/lib/rules/jsx-boolean-value.js

+49-12
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ ruleTester.run('jsx-boolean-value', rule, {
6363
output: '<App foo />;',
6464
options: ['never'],
6565
errors: [
66-
{ messageId: 'omitBoolean_noMessage' },
66+
{
67+
messageId: 'omitBoolean',
68+
data: { propName: 'foo' },
69+
},
6770
],
6871
},
6972
{
@@ -73,34 +76,43 @@ ruleTester.run('jsx-boolean-value', rule, {
7376
errors: [
7477
{
7578
messageId: 'omitBoolean',
76-
data: { exceptionsMessage: ' for the following props: `foo`, `bar`' },
79+
data: { propName: 'foo' },
7780
},
7881
{
7982
messageId: 'omitBoolean',
80-
data: { exceptionsMessage: ' for the following props: `foo`, `bar`' },
83+
data: { propName: 'bar' },
8184
},
8285
],
8386
},
8487
{
8588
code: '<App foo={true} />;',
8689
output: '<App foo />;',
8790
errors: [
88-
{ messageId: 'omitBoolean_noMessage' },
91+
{
92+
messageId: 'omitBoolean',
93+
data: { propName: 'foo' },
94+
},
8995
],
9096
},
9197
{
9298
code: '<App foo = {true} />;',
9399
output: '<App foo />;',
94100
errors: [
95-
{ messageId: 'omitBoolean_noMessage' },
101+
{
102+
messageId: 'omitBoolean',
103+
data: { propName: 'foo' },
104+
},
96105
],
97106
},
98107
{
99108
code: '<App foo />;',
100109
output: '<App foo={true} />;',
101110
options: ['always'],
102111
errors: [
103-
{ messageId: 'setBoolean_noMessage' },
112+
{
113+
messageId: 'setBoolean',
114+
data: { propName: 'foo' },
115+
},
104116
],
105117
},
106118
{
@@ -110,11 +122,11 @@ ruleTester.run('jsx-boolean-value', rule, {
110122
errors: [
111123
{
112124
messageId: 'setBoolean',
113-
data: { exceptionsMessage: ' for the following props: `foo`, `bar`' },
125+
data: { propName: 'foo' },
114126
},
115127
{
116128
messageId: 'setBoolean',
117-
data: { exceptionsMessage: ' for the following props: `foo`, `bar`' },
129+
data: { propName: 'bar' },
118130
},
119131
],
120132
},
@@ -123,8 +135,14 @@ ruleTester.run('jsx-boolean-value', rule, {
123135
output: '<App />;',
124136
options: ['never', { assumeUndefinedIsFalse: true }],
125137
errors: [
126-
{ messageId: 'omitPropAndBoolean_noMessage' },
127-
{ messageId: 'omitPropAndBoolean_noMessage' },
138+
{
139+
messageId: 'omitPropAndBoolean',
140+
data: { propName: 'foo' },
141+
},
142+
{
143+
messageId: 'omitPropAndBoolean',
144+
data: { propName: 'bak' },
145+
},
128146
],
129147
},
130148
{
@@ -137,11 +155,30 @@ ruleTester.run('jsx-boolean-value', rule, {
137155
errors: [
138156
{
139157
messageId: 'omitPropAndBoolean',
140-
data: { exceptionsMessage: ' for the following props: `baz`, `bak`' },
158+
data: { propName: 'baz' },
141159
},
142160
{
143161
messageId: 'omitPropAndBoolean',
144-
data: { exceptionsMessage: ' for the following props: `baz`, `bak`' },
162+
data: { propName: 'bak' },
163+
},
164+
],
165+
},
166+
{
167+
code: '<App foo={true} bar={true} baz />;',
168+
output: '<App foo bar baz={true} />;',
169+
options: ['always', { never: ['foo', 'bar'] }],
170+
errors: [
171+
{
172+
messageId: 'omitBoolean',
173+
data: { propName: 'foo' },
174+
},
175+
{
176+
messageId: 'omitBoolean',
177+
data: { propName: 'bar' },
178+
},
179+
{
180+
messageId: 'setBoolean',
181+
data: { propName: 'baz' },
145182
},
146183
],
147184
},

0 commit comments

Comments
 (0)