Skip to content

Commit 71abb44

Browse files
Potential autofix improvement for jsx-wrap-mulitlines
This change should remove the newline that comes before a parentheses, if "parens-new-line" is specified as option and the multiline jsx starts on a new line. The autofix will also inject the closing parentheses before the next enclosing character as opposed to being on its own line.
1 parent c7dd755 commit 71abb44

File tree

2 files changed

+47
-12
lines changed

2 files changed

+47
-12
lines changed

lib/rules/jsx-wrap-multilines.js

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,21 @@ module.exports = {
104104
return node.loc.start.line !== node.loc.end.line;
105105
}
106106

107-
function report(node, message, fixerFn) {
107+
function report(node, message, fix) {
108108
context.report({
109-
node: node,
110-
message: message,
111-
fix: fixerFn
109+
node,
110+
message,
111+
fix
112112
});
113113
}
114114

115+
function trimTokenBeforeNewline(node, tokenBefore) {
116+
// if the token before the jsx is a bracket or curly brace
117+
// we don't want a space between the opening parentheses and the multiline jsx
118+
const isBracket = tokenBefore.value === '{' || tokenBefore.value === '[';
119+
return `${tokenBefore.value.trim()}${isBracket ? '' : ' '}`;
120+
}
121+
115122
function check(node, type) {
116123
if (!node || node.type !== 'JSXElement') {
117124
return;
@@ -125,7 +132,21 @@ module.exports = {
125132

126133
if (option === 'parens-new-line' && isMultilines(node)) {
127134
if (!isParenthesised(node)) {
128-
report(node, MISSING_PARENS, fixer => fixer.replaceText(node, `(\n${sourceCode.getText(node)}\n)`));
135+
const tokenBefore = sourceCode.getTokenBefore(node, {includeComments: true});
136+
const tokenAfter = sourceCode.getTokenAfter(node, {includeComments: true});
137+
if (tokenBefore.loc.end.line < node.loc.start.line) {
138+
// Strip newline after operator if parens newline is specified
139+
report(
140+
node,
141+
MISSING_PARENS,
142+
fixer => fixer.replaceTextRange(
143+
[tokenBefore.range[0], tokenAfter.range[0]],
144+
`${trimTokenBeforeNewline(node, tokenBefore)}(\n${sourceCode.getText(node)}\n)`
145+
)
146+
);
147+
} else {
148+
report(node, MISSING_PARENS, fixer => fixer.replaceText(node, `(\n${sourceCode.getText(node)}\n)`));
149+
}
129150
} else if (needsNewLines(node)) {
130151
report(node, PARENS_NEW_LINES, fixer => fixer.replaceText(node, `\n${sourceCode.getText(node)}\n`));
131152
}
@@ -135,7 +156,6 @@ module.exports = {
135156
// --------------------------------------------------------------------------
136157
// Public
137158
// --------------------------------------------------------------------------
138-
139159
return {
140160

141161
VariableDeclarator: function(node) {
@@ -171,7 +191,7 @@ module.exports = {
171191
}
172192
},
173193

174-
'ArrowFunctionExpression:exit': function (node) {
194+
'ArrowFunctionExpression:exit': function(node) {
175195
const arrowBody = node.body;
176196
const type = 'arrow';
177197

@@ -195,7 +215,7 @@ module.exports = {
195215
}
196216
},
197217

198-
JSXAttribute: function (node) {
218+
JSXAttribute: function(node) {
199219
const type = 'prop';
200220
if (isEnabled(type) && node.value && node.value.type === 'JSXExpressionContainer') {
201221
check(node.value.expression, type);

tests/lib/rules/jsx-wrap-multilines.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,14 @@ const LOGICAL_NO_PAREN = `
249249
</div>
250250
`;
251251

252+
const LOGICAL_PAREN_NEW_LINE_AUTOFIX = `
253+
<div>
254+
{foo && (\n<div>
255+
<p>Hello World</p>
256+
</div>\n)}
257+
</div>
258+
`;
259+
252260
const LOGICAL_PAREN_NEW_LINE = `
253261
<div>
254262
{foo && (
@@ -291,6 +299,14 @@ const ATTR_PAREN_NEW_LINE = `
291299
</div>
292300
`;
293301

302+
const ATTR_PAREN_NEW_LINE_AUTOFIX = `
303+
<div prop={(\n<div>
304+
<p>Hello</p>
305+
</div>\n)}>
306+
<p>Hello</p>
307+
</div>
308+
`;
309+
294310
function addNewLineSymbols(code) {
295311
return code.replace(/\(</g, '(\n<').replace(/>\)/g, '>\n)');
296312
}
@@ -640,7 +656,7 @@ ruleTester.run('jsx-wrap-multilines', rule, {
640656
errors: [{message: PARENS_NEW_LINES}]
641657
}, {
642658
code: LOGICAL_NO_PAREN,
643-
output: addNewLineSymbols(LOGICAL_PAREN),
659+
output: LOGICAL_PAREN_NEW_LINE_AUTOFIX,
644660
options: [{logical: 'parens-new-line'}],
645661
errors: [{message: MISSING_PARENS}]
646662
}, {
@@ -650,9 +666,8 @@ ruleTester.run('jsx-wrap-multilines', rule, {
650666
errors: [{message: PARENS_NEW_LINES}]
651667
}, {
652668
code: ATTR_NO_PAREN,
653-
output: addNewLineSymbols(ATTR_PAREN),
669+
output: ATTR_PAREN_NEW_LINE_AUTOFIX,
654670
options: [{prop: 'parens-new-line'}],
655671
errors: [{message: MISSING_PARENS}]
656-
}
657-
]
672+
}]
658673
});

0 commit comments

Comments
 (0)