Skip to content

Commit facb65b

Browse files
karolina-benitezljharb
authored andcommitted
[Fix] jsx-props-no-multi-spaces: "Expected no line gap between" false positive
Fixes #2774.
1 parent 08eda7a commit facb65b

File tree

3 files changed

+113
-1
lines changed

3 files changed

+113
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
2020
* [`jsx-closing-bracket-location`]: In `tag-aligned`, made a distinction between tabs and spaces ([#2796][] @Moong0122)
2121
* [`jsx-handler-names`]: false positive when handler name begins with number ([#1689][] @jsphstls)
2222
* [`prop-types`]: Detect JSX returned by sequential expression ([#2801][] @mikol)
23+
* [`jsx-props-no-multi-spaces`]: "Expected no line gap between" false positive ([#2792][] @karolina-benitez)
2324

2425
### Changed
2526
* [Tests] [`jsx-one-expression-per-line`]: add passing tests ([#2799][] @TaLeaMonet)
2627

2728
[#2801]: https://github.com/yannickcr/eslint-plugin-react/pull/2801
2829
[#2799]: https://github.com/yannickcr/eslint-plugin-react/pull/2799
2930
[#2796]: https://github.com/yannickcr/eslint-plugin-react/pull/2796
31+
[#2792]: https://github.com/yannickcr/eslint-plugin-react/pull/2792
3032
[#2791]: https://github.com/yannickcr/eslint-plugin-react/pull/2791
3133
[#2789]: https://github.com/yannickcr/eslint-plugin-react/pull/2789
3234
[#2782]: https://github.com/yannickcr/eslint-plugin-react/pull/2782

lib/rules/jsx-props-no-multi-spaces.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ module.exports = {
2424
},
2525

2626
create(context) {
27+
const sourceCode = context.getSourceCode();
28+
2729
function getPropName(propNode) {
2830
switch (propNode.type) {
2931
case 'JSXSpreadAttribute':
@@ -37,11 +39,30 @@ module.exports = {
3739
}
3840
}
3941

42+
function hasEmptyLines(node, leadingLineCount) {
43+
const allComments = sourceCode.getCommentsBefore(node);
44+
let commentLines = 0;
45+
46+
if (allComments.length > 0) {
47+
allComments.forEach((comment) => {
48+
const start = comment.loc.start.line;
49+
const end = comment.loc.end.line;
50+
51+
commentLines += (end - start + 1);
52+
});
53+
54+
return commentLines !== leadingLineCount;
55+
}
56+
57+
return true;
58+
}
59+
4060
function checkSpacing(prev, node) {
4161
const prevNodeEndLine = prev.loc.end.line;
4262
const currNodeStartLine = node.loc.start.line;
63+
const leadingLineCount = currNodeStartLine - prevNodeEndLine - 1;
4364

44-
if (currNodeStartLine - prevNodeEndLine > 1) {
65+
if (leadingLineCount > 0 && hasEmptyLines(node, leadingLineCount)) {
4566
context.report({
4667
node,
4768
message: `Expected no line gap between “${getPropName(prev)}” and “${getPropName(node)}”`

tests/lib/rules/jsx-props-no-multi-spaces.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,42 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
8585
type="button"
8686
/>
8787
`
88+
}, {
89+
code: `
90+
<button
91+
title="Some button"
92+
// this is a comment
93+
onClick={(value) => {
94+
console.log(value);
95+
}}
96+
type="button"
97+
/>
98+
`
99+
}, {
100+
code: `
101+
<button
102+
title="Some button"
103+
// this is a comment
104+
// this is a second comment
105+
onClick={(value) => {
106+
console.log(value);
107+
}}
108+
type="button"
109+
/>
110+
`
111+
}, {
112+
code: `
113+
<button
114+
title="Some button"
115+
/* this is a multiline comment
116+
...
117+
... */
118+
onClick={(value) => {
119+
console.log(value);
120+
}}
121+
type="button"
122+
/>
123+
`
88124
}],
89125

90126
invalid: [{
@@ -170,5 +206,58 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
170206
{message: 'Expected no line gap between “title” and “onClick”'},
171207
{message: 'Expected no line gap between “onClick” and “type”'}
172208
]
209+
}, {
210+
code: `
211+
<button
212+
title="Some button"
213+
// this is a comment
214+
onClick={(value) => {
215+
console.log(value);
216+
}}
217+
218+
type="button"
219+
/>
220+
`,
221+
errors: [
222+
{message: 'Expected no line gap between “onClick” and “type”'}
223+
]
224+
}, {
225+
code: `
226+
<button
227+
title="Some button"
228+
// this is a comment
229+
// second comment
230+
231+
onClick={(value) => {
232+
console.log(value);
233+
}}
234+
235+
type="button"
236+
/>
237+
`,
238+
errors: [
239+
{message: 'Expected no line gap between “title” and “onClick”'},
240+
{message: 'Expected no line gap between “onClick” and “type”'}
241+
]
242+
}, {
243+
code: `
244+
<button
245+
title="Some button"
246+
/*this is a
247+
multiline
248+
comment
249+
*/
250+
251+
onClick={(value) => {
252+
console.log(value);
253+
}}
254+
255+
type="button"
256+
/>
257+
`,
258+
errors: [
259+
{message: 'Expected no line gap between “title” and “onClick”'},
260+
{message: 'Expected no line gap between “onClick” and “type”'}
261+
]
173262
}]
174263
});

0 commit comments

Comments
 (0)