Skip to content

Commit 9b2db61

Browse files
vedadeeptaljharb
authored andcommitted
[fix] jsx-curly-brace-presence: report unnecessary curly braces with children on next line
1 parent 781bfff commit 9b2db61

File tree

2 files changed

+119
-6
lines changed

2 files changed

+119
-6
lines changed

lib/rules/jsx-curly-brace-presence.js

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -205,17 +205,44 @@ module.exports = {
205205
);
206206
}
207207

208-
function shouldCheckForUnnecessaryCurly(parent, config) {
209-
// If there are more than one JSX child, there is no need to check for
210-
// unnecessary curly braces.
211-
if (jsxUtil.isJSX(parent) && parent.children.length !== 1) {
208+
function isWhiteSpaceLiteral(node) {
209+
return node.type && node.type === 'Literal' && node.value && !(/\S/.test(node.value));
210+
}
211+
212+
function getAdjacentSiblings(node, children) {
213+
for (let i = 1; i < children.length - 1; i++) {
214+
const child = children[i];
215+
if (node === child) {
216+
return [children[i - 1], children[i + 1]];
217+
}
218+
}
219+
if (node === children[0] && children[1]) {
220+
return [children[1]];
221+
}
222+
if (node === children[children.length - 1] && children[children.length - 2]) {
223+
return [children[children.length - 2]];
224+
}
225+
return [];
226+
}
227+
228+
function hasAdjacentJsxExpressionContainers(node, children) {
229+
const childrenExcludingWhitespaceLiteral = children.filter(child => !isWhiteSpaceLiteral(child));
230+
const adjSiblings = getAdjacentSiblings(node, childrenExcludingWhitespaceLiteral);
231+
232+
return adjSiblings.some(x => x.type && x.type === 'JSXExpressionContainer');
233+
}
234+
235+
function shouldCheckForUnnecessaryCurly(parent, node, config) {
236+
// If there are adjacent `JsxExpressionContainer` then there is no need,
237+
// to check for unnecessary curly braces.
238+
if (jsxUtil.isJSX(parent) && hasAdjacentJsxExpressionContainers(node, parent.children)) {
212239
return false;
213240
}
214241

215242
if (
216243
parent.children &&
217244
parent.children.length === 1 &&
218-
containsWhitespaceExpression(parent.children[0])
245+
containsWhitespaceExpression(node)
219246
) {
220247
return false;
221248
}
@@ -241,7 +268,7 @@ module.exports = {
241268

242269
return {
243270
JSXExpressionContainer: (node) => {
244-
if (shouldCheckForUnnecessaryCurly(node.parent, userConfig)) {
271+
if (shouldCheckForUnnecessaryCurly(node.parent, node, userConfig)) {
245272
lintUnnecessaryCurly(node);
246273
}
247274
},

tests/lib/rules/jsx-curly-brace-presence.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,25 @@ ruleTester.run('jsx-curly-brace-presence', rule, {
284284
\`}</App>
285285
`,
286286
options: ['always']
287+
},
288+
{
289+
code: `
290+
<MyComponent>
291+
%
292+
</MyComponent>
293+
`,
294+
parser: parsers.BABEL_ESLINT,
295+
options: [{children: 'never'}]
296+
},
297+
{
298+
code: `
299+
<MyComponent>
300+
foo
301+
<div>bar</div>
302+
</MyComponent>
303+
`,
304+
parser: parsers.BABEL_ESLINT,
305+
options: [{children: 'never'}]
287306
}
288307
],
289308

@@ -335,6 +354,73 @@ ruleTester.run('jsx-curly-brace-presence', rule, {
335354
options: [{props: 'never'}],
336355
errors: [{message: unnecessaryCurlyMessage}]
337356
},
357+
{
358+
code: `
359+
<MyComponent>
360+
{'%'}
361+
</MyComponent>
362+
`,
363+
output: `
364+
<MyComponent>
365+
%
366+
</MyComponent>
367+
`,
368+
parser: parsers.BABEL_ESLINT,
369+
options: [{children: 'never'}],
370+
errors: [{message: unnecessaryCurlyMessage}]
371+
},
372+
{
373+
code: `
374+
<MyComponent>
375+
{'foo'}
376+
<div>
377+
{'bar'}
378+
</div>
379+
{'baz'}
380+
</MyComponent>
381+
`,
382+
output: `
383+
<MyComponent>
384+
foo
385+
<div>
386+
bar
387+
</div>
388+
baz
389+
</MyComponent>
390+
`,
391+
parser: parsers.BABEL_ESLINT,
392+
options: [{children: 'never'}],
393+
errors: [
394+
{message: unnecessaryCurlyMessage},
395+
{message: unnecessaryCurlyMessage},
396+
{message: unnecessaryCurlyMessage}
397+
]
398+
},
399+
{
400+
code: `
401+
<MyComponent>
402+
{'foo'}
403+
<div>
404+
{'bar'}
405+
</div>
406+
{'baz'}
407+
{'some-complicated-exp'}
408+
</MyComponent>
409+
`,
410+
output: `
411+
<MyComponent>
412+
foo
413+
<div>
414+
bar
415+
</div>
416+
{'baz'}
417+
{'some-complicated-exp'}
418+
</MyComponent>
419+
`,
420+
parser: parsers.BABEL_ESLINT,
421+
options: [{children: 'never'}],
422+
errors: [{message: unnecessaryCurlyMessage}, {message: unnecessaryCurlyMessage}]
423+
},
338424
{
339425
code: `<MyComponent prop='bar'>foo</MyComponent>`,
340426
output: '<MyComponent prop={"bar"}>foo</MyComponent>',

0 commit comments

Comments
 (0)