From 6a41c600be7d3ee0d16a92b283f918e5e7da9ac1 Mon Sep 17 00:00:00 2001 From: Sharmila Date: Wed, 29 Nov 2017 19:28:48 -0800 Subject: [PATCH] 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. --- lib/rules/jsx-wrap-multilines.js | 35 ++++++++++++++++++++------ tests/lib/rules/jsx-wrap-multilines.js | 27 +++++++++++++++++--- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/lib/rules/jsx-wrap-multilines.js b/lib/rules/jsx-wrap-multilines.js index 0e2223f5e6..a42741eeb0 100644 --- a/lib/rules/jsx-wrap-multilines.js +++ b/lib/rules/jsx-wrap-multilines.js @@ -104,14 +104,21 @@ module.exports = { return node.loc.start.line !== node.loc.end.line; } - function report(node, message, fixerFn) { + function report(node, message, fix) { context.report({ - node: node, - message: message, - fix: fixerFn + node, + message, + fix }); } + function trimTokenBeforeNewline(node, tokenBefore) { + // if the token before the jsx is a bracket or curly brace + // we don't want a space between the opening parentheses and the multiline jsx + const isBracket = tokenBefore.value === '{' || tokenBefore.value === '['; + return `${tokenBefore.value.trim()}${isBracket ? '' : ' '}`; + } + function check(node, type) { if (!node || node.type !== 'JSXElement') { return; @@ -125,7 +132,21 @@ module.exports = { if (option === 'parens-new-line' && isMultilines(node)) { if (!isParenthesised(node)) { - report(node, MISSING_PARENS, fixer => fixer.replaceText(node, `(\n${sourceCode.getText(node)}\n)`)); + const tokenBefore = sourceCode.getTokenBefore(node, {includeComments: true}); + const tokenAfter = sourceCode.getTokenAfter(node, {includeComments: true}); + if (tokenBefore.loc.end.line < node.loc.start.line) { + // Strip newline after operator if parens newline is specified + report( + node, + MISSING_PARENS, + fixer => fixer.replaceTextRange( + [tokenBefore.range[0], tokenAfter.range[0]], + `${trimTokenBeforeNewline(node, tokenBefore)}(\n${sourceCode.getText(node)}\n)` + ) + ); + } else { + report(node, MISSING_PARENS, fixer => fixer.replaceText(node, `(\n${sourceCode.getText(node)}\n)`)); + } } else if (needsNewLines(node)) { report(node, PARENS_NEW_LINES, fixer => fixer.replaceText(node, `\n${sourceCode.getText(node)}\n`)); } @@ -171,7 +192,7 @@ module.exports = { } }, - 'ArrowFunctionExpression:exit': function (node) { + 'ArrowFunctionExpression:exit': function(node) { const arrowBody = node.body; const type = 'arrow'; @@ -195,7 +216,7 @@ module.exports = { } }, - JSXAttribute: function (node) { + JSXAttribute: function(node) { const type = 'prop'; if (isEnabled(type) && node.value && node.value.type === 'JSXExpressionContainer') { check(node.value.expression, type); diff --git a/tests/lib/rules/jsx-wrap-multilines.js b/tests/lib/rules/jsx-wrap-multilines.js index 202e308387..14727136af 100644 --- a/tests/lib/rules/jsx-wrap-multilines.js +++ b/tests/lib/rules/jsx-wrap-multilines.js @@ -249,6 +249,16 @@ const LOGICAL_NO_PAREN = ` `; +const LOGICAL_PAREN_NEW_LINE_AUTOFIX = ` +
+ {foo && ( +
+

Hello World

+
+)} +
+`; + const LOGICAL_PAREN_NEW_LINE = `
{foo && ( @@ -291,6 +301,16 @@ const ATTR_PAREN_NEW_LINE = `
`; +const ATTR_PAREN_NEW_LINE_AUTOFIX = ` +
+

Hello

+
+)}> +

Hello

+ +`; + function addNewLineSymbols(code) { return code.replace(/\(\)/g, '>\n)'); } @@ -640,7 +660,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { errors: [{message: PARENS_NEW_LINES}] }, { code: LOGICAL_NO_PAREN, - output: addNewLineSymbols(LOGICAL_PAREN), + output: LOGICAL_PAREN_NEW_LINE_AUTOFIX, options: [{logical: 'parens-new-line'}], errors: [{message: MISSING_PARENS}] }, { @@ -650,9 +670,8 @@ ruleTester.run('jsx-wrap-multilines', rule, { errors: [{message: PARENS_NEW_LINES}] }, { code: ATTR_NO_PAREN, - output: addNewLineSymbols(ATTR_PAREN), + output: ATTR_PAREN_NEW_LINE_AUTOFIX, options: [{prop: 'parens-new-line'}], errors: [{message: MISSING_PARENS}] - } - ] + }] });