Skip to content

Commit b4b7497

Browse files
reedwsljharb
authored andcommitted
[New] jsx-wrap-multilines: add never option to prohibit wrapping parens on multiline JSX
1 parent 37d8bbe commit b4b7497

File tree

4 files changed

+469
-8
lines changed

4 files changed

+469
-8
lines changed

Diff for: CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
1212
* [`no-unknown-property`]: add `displaystyle` on `<math>` ([#3652][] @lounsbrough)
1313
* [`prefer-read-only-props`], [`prop-types`], component detection: allow components to be async functions ([#3654][] @pnodet)
1414
* [`no-unknown-property`]: support `onResize` on audio/video tags ([#3662][] @caesar1030)
15+
* [`jsx-wrap-multilines`]: add `never` option to prohibit wrapping parens on multiline JSX ([#3668][] @reedws)
1516

1617
### Fixed
1718
* [`jsx-no-leaked-render`]: preserve RHS parens for multiline jsx elements while fixing ([#3623][] @akulsr0)
@@ -26,6 +27,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
2627
* [Refactor] [`jsx-props-no-multi-spaces`]: extract type parameters to var ([#3634][] @HenryBrown0)
2728
* [Docs] [`jsx-key`]: fix correct example ([#3656][] @developer-bandi)
2829

30+
[#3668]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3668
2931
[#3666]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3666
3032
[#3662]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3662
3133
[#3656]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3656

Diff for: docs/rules/jsx-wrap-multilines.md

+230-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ var Hello = createReactClass({
5050
});
5151
```
5252

53-
Examples of **correct** code for this rule:
53+
Examples of **correct** code for this rule, when configured with either `parens` or `parens-new-line`:
5454

5555
```jsx
5656
var singleLineJSX = <p>Hello</p>
@@ -66,6 +66,36 @@ var Hello = createReactClass({
6666
});
6767
```
6868

69+
Examples of **incorrect** code for this rule, when configured with `never`:
70+
71+
```jsx
72+
var singleLineJSX = <p>Hello</p>
73+
74+
var Hello = createReactClass({
75+
render: function() {
76+
return (
77+
<div>
78+
<p>Hello {this.props.name}</p>
79+
</div>
80+
);
81+
}
82+
});
83+
```
84+
85+
Examples of **correct** code for this rule, when configured with `never`:
86+
87+
```jsx
88+
var singleLineJSX = <p>Hello</p>
89+
90+
var Hello = createReactClass({
91+
render: function() {
92+
return <div>
93+
<p>Hello {this.props.name}</p>
94+
</div>;
95+
}
96+
});
97+
```
98+
6999
### `declaration`
70100

71101
Examples of **incorrect** code for this rule, when configured with `{ declaration: "parens" }`:
@@ -116,6 +146,30 @@ var hello = (
116146
);
117147
```
118148

149+
Examples of **incorrect** code for this rule, when configured with `{ declaration: "never" }`:
150+
151+
```jsx
152+
var hello = (<div>
153+
<p>Hello</p>
154+
</div>);
155+
```
156+
157+
```jsx
158+
var hello = (
159+
<div>
160+
<p>Hello</p>
161+
</div>
162+
);
163+
```
164+
165+
Examples of **correct** code for this rule, when configured with `{ declaration: "never" }`.
166+
167+
```jsx
168+
var hello = <div>
169+
<p>Hello</p>
170+
</div>;
171+
```
172+
119173
### `assignment`
120174

121175
Examples of **incorrect** code for this rule, when configured with `{ assignment: "parens" }`.
@@ -172,6 +226,33 @@ hello = (
172226
);
173227
```
174228

229+
Examples of **incorrect** code for this rule, when configured with `{ assignment: "never" }`.
230+
231+
```jsx
232+
var hello;
233+
hello = (<div>
234+
<p>Hello</p>
235+
</div>);
236+
```
237+
238+
```jsx
239+
var hello;
240+
hello = (
241+
<div>
242+
<p>Hello</p>
243+
</div>
244+
);
245+
```
246+
247+
Examples of **correct** code for this rule, when configured with `{ assignment: "never" }`.
248+
249+
```jsx
250+
var hello;
251+
hello = <div>
252+
<p>Hello</p>
253+
</div>;
254+
```
255+
175256
### `return`
176257

177258
Examples of **incorrect** code for this rule, when configured with `{ return: "parens" }`.
@@ -234,6 +315,36 @@ function hello() {
234315
}
235316
```
236317

318+
Examples of **incorrect** code for this rule, when configured with `{ return: "never" }`.
319+
320+
```jsx
321+
function hello() {
322+
return (<div>
323+
<p>Hello</p>
324+
</div>);
325+
}
326+
```
327+
328+
```jsx
329+
function hello() {
330+
return (
331+
<div>
332+
<p>Hello</p>
333+
</div>
334+
);
335+
}
336+
```
337+
338+
Examples of **correct** code for this rule, when configured with `{ return: "never" }`.
339+
340+
```jsx
341+
function hello() {
342+
return <div>
343+
<p>Hello</p>
344+
</div>;
345+
}
346+
```
347+
237348
### `arrow`
238349

239350
Examples of **incorrect** code for this rule, when configured with `{ arrow: "parens" }`.
@@ -284,6 +395,30 @@ var hello = () => (
284395
);
285396
```
286397

398+
Examples of **incorrect** code for this rule, when configured with `{ arrow: "never" }`.
399+
400+
```jsx
401+
var hello = () => (<div>
402+
<p>World</p>
403+
</div>);
404+
```
405+
406+
```jsx
407+
var hello = () => (
408+
<div>
409+
<p>World</p>
410+
</div>
411+
);
412+
```
413+
414+
Examples of **correct** code for this rule, when configured with `{ arrow: "never" }`.
415+
416+
```jsx
417+
var hello = () => <div>
418+
<p>World</p>
419+
</div>;
420+
```
421+
287422
### `condition`
288423

289424
Examples of **incorrect** code for this rule, when configured with `{ condition: "parens" }`.
@@ -346,6 +481,36 @@ Examples of **correct** code for this rule, when configured with `{ condition: "
346481
</div>
347482
```
348483

484+
Examples of **incorrect** code for this rule, when configured with `{ condition: "never" }`.
485+
486+
```jsx
487+
<div>
488+
{foo ? (<div>
489+
<p>Hello</p>
490+
</div>) : null}
491+
</div>
492+
```
493+
494+
```jsx
495+
<div>
496+
{foo ? (
497+
<div>
498+
<p>Hello</p>
499+
</div>
500+
): null}
501+
</div>
502+
```
503+
504+
Examples of **correct** code for this rule, when configured with `{ condition: "never" }`.
505+
506+
```jsx
507+
<div>
508+
{foo ? <div>
509+
<p>Hello</p>
510+
</div> : null}
511+
</div>
512+
```
513+
349514
### `logical`
350515

351516
Examples of **incorrect** code for this rule, when configured with `{ logical: "parens" }`.
@@ -416,6 +581,40 @@ Examples of **correct** code for this rule, when configured with `{ logical: "pa
416581
</div>
417582
```
418583

584+
Examples of **incorrect** code for this rule, when configured with `{ logical: "never" }`.
585+
586+
```jsx
587+
<div>
588+
{foo &&
589+
(<div>
590+
<p>Hello World</p>
591+
</div>)
592+
}
593+
</div>
594+
```
595+
596+
```jsx
597+
<div>
598+
{foo && (
599+
<div>
600+
<p>Hello World</p>
601+
</div>
602+
)}
603+
</div>
604+
```
605+
606+
Examples of **correct** code for this rule, when configured with `{ logical: "never" }`.
607+
608+
```jsx
609+
<div>
610+
{foo &&
611+
<div>
612+
<p>Hello World</p>
613+
</div>
614+
}
615+
</div>
616+
```
617+
419618
### `prop`
420619

421620
Examples of **incorrect** code for this rule, when configured with `{ prop: "parens" }`.
@@ -477,3 +676,33 @@ Examples of **correct** code for this rule, when configured with `{ prop: "paren
477676
<p>Hello</p>
478677
</div>;
479678
```
679+
680+
Examples of **incorrect** code for this rule, when configured with `{ prop: "never" }`.
681+
682+
```jsx
683+
<div foo={(<div>
684+
<p>Hello</p>
685+
</div>)}>
686+
<p>Hello</p>
687+
</div>;
688+
```
689+
690+
```jsx
691+
<div foo={(
692+
<div>
693+
<p>Hello</p>
694+
</div>
695+
)}>
696+
<p>Hello</p>
697+
</div>;
698+
```
699+
700+
Examples of **correct** code for this rule, when configured with `{ prop: "never" }`.
701+
702+
```jsx
703+
<div foo={<div>
704+
<p>Hello</p>
705+
</div>}>
706+
<p>Hello</p>
707+
</div>;
708+
```

Diff for: lib/rules/jsx-wrap-multilines.js

+17-7
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const DEFAULTS = {
3131

3232
const messages = {
3333
missingParens: 'Missing parentheses around multilines JSX',
34+
extraParens: 'Expected no parentheses around multilines JSX',
3435
parensOnNewLines: 'Parentheses around JSX should be on separate lines',
3536
};
3637

@@ -51,25 +52,25 @@ module.exports = {
5152
// true/false are for backwards compatibility
5253
properties: {
5354
declaration: {
54-
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
55+
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
5556
},
5657
assignment: {
57-
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
58+
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
5859
},
5960
return: {
60-
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
61+
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
6162
},
6263
arrow: {
63-
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
64+
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
6465
},
6566
condition: {
66-
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
67+
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
6768
},
6869
logical: {
69-
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
70+
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
7071
},
7172
prop: {
72-
enum: [true, false, 'ignore', 'parens', 'parens-new-line'],
73+
enum: [true, false, 'ignore', 'parens', 'parens-new-line', 'never'],
7374
},
7475
},
7576
additionalProperties: false,
@@ -184,6 +185,15 @@ module.exports = {
184185
}
185186
}
186187
}
188+
189+
if (option === 'never' && isParenthesized(context, node)) {
190+
const tokenBefore = sourceCode.getTokenBefore(node);
191+
const tokenAfter = sourceCode.getTokenAfter(node);
192+
report(node, 'extraParens', (fixer) => fixer.replaceTextRange(
193+
[tokenBefore.range[0], tokenAfter.range[1]],
194+
sourceCode.getText(node)
195+
));
196+
}
187197
}
188198

189199
// --------------------------------------------------------------------------

0 commit comments

Comments
 (0)