diff --git a/docs/rules/jsx-wrap-multilines.md b/docs/rules/jsx-wrap-multilines.md index 3179f8cca3..933fb46c74 100644 --- a/docs/rules/jsx-wrap-multilines.md +++ b/docs/rules/jsx-wrap-multilines.md @@ -1,11 +1,24 @@ # Prevent missing parentheses around multiline JSX (jsx-wrap-multilines) -Wrapping multiline JSX in parentheses can improve readability and/or convenience. It optionally takes a second parameter in the form of an object, containing places to apply the rule. By default, `"declaration"`, `"assignment"`, and `"return"` syntax is checked, but these can be explicitly disabled. Any syntax type missing in the object will follow the default behavior (become enabled). +Wrapping multiline JSX in parentheses can improve readability and/or convenience*. It optionally takes a second parameter in the form of an object, containing places to apply the rule. By default, `"declaration"`, `"assignment"`, and `"return"` syntax is checked, but these can be explicitly disabled. Any syntax type missing in the object will follow the default behavior (become enabled). + +* however, the default style option is "always", this means use parentheses. But you can also set it to "never" and disallow parentheses around your jsx if want to. **Fixable:** This rule is automatically fixable using the `--fix` flag on the command line. ## Rule Details +Options + +```js +"react/jsx-wrap-multilines": ["error", { + "style": "always|never", // default "always" + "assignment": bool, // default true + "declaration": bool, // default true + "return": bool, // default true +}] +``` + The following patterns are considered warnings: ```js diff --git a/lib/rules/jsx-wrap-multilines.js b/lib/rules/jsx-wrap-multilines.js index 7ee23e706c..04cdda3eb0 100644 --- a/lib/rules/jsx-wrap-multilines.js +++ b/lib/rules/jsx-wrap-multilines.js @@ -11,6 +11,7 @@ var has = require('has'); // ------------------------------------------------------------------------------ var DEFAULTS = { + style: 'always', declaration: true, assignment: true, return: true @@ -32,6 +33,10 @@ module.exports = { schema: [{ type: 'object', properties: { + style: { + type: 'string', + enum: ['always', 'never'] + }, declaration: { type: 'boolean' }, @@ -50,6 +55,14 @@ module.exports = { var sourceCode = context.getSourceCode(); + function isEnabled(type) { + var userOptions = context.options[0] || {}; + if (has(userOptions, type)) { + return userOptions[type]; + } + return DEFAULTS[type]; + } + function isParenthesised(node) { var previousToken = sourceCode.getTokenBefore(node); var nextToken = sourceCode.getTokenAfter(node); @@ -68,7 +81,8 @@ module.exports = { return; } - if (!isParenthesised(node) && isMultilines(node)) { + var style = isEnabled('style'); + if (style === 'always' && !isParenthesised(node) && isMultilines(node)) { context.report({ node: node, message: 'Missing parentheses around multilines JSX', @@ -77,14 +91,25 @@ module.exports = { } }); } - } - function isEnabled(type) { - var userOptions = context.options[0] || {}; - if (has(userOptions, type)) { - return userOptions[type]; + if (style === 'never' && isParenthesised(node)) { + context.report({ + node: node, + message: 'Parentheses around JSX are not allowed', + fix: function(fixer) { + // Taken from 'no-extra-parens' + // https://github.com/eslint/eslint/blob/master/lib/rules/no-extra-parens.js#L338 + var leftParenToken = sourceCode.getTokenBefore(node); + var rightParenToken = sourceCode.getTokenAfter(node); + var parenthesizedSource = sourceCode.text.slice(leftParenToken.range[1], rightParenToken.range[0]); + + return fixer.replaceTextRange([ + leftParenToken.range[0], + rightParenToken.range[1] + ], parenthesizedSource); + } + }); } - return DEFAULTS[type]; } // -------------------------------------------------------------------------- @@ -92,7 +117,6 @@ module.exports = { // -------------------------------------------------------------------------- return { - VariableDeclarator: function(node) { if (!isEnabled('declaration')) { return; diff --git a/tests/lib/rules/jsx-wrap-multilines.js b/tests/lib/rules/jsx-wrap-multilines.js index f6d50454d9..6f30e3ee82 100644 --- a/tests/lib/rules/jsx-wrap-multilines.js +++ b/tests/lib/rules/jsx-wrap-multilines.js @@ -166,6 +166,18 @@ ruleTester.run('jsx-wrap-multilines', rule, { code: ASSIGNMENT_NO_PAREN, options: [{assignment: false}], parserOptions: parserOptions + }, { + code: ASSIGNMENT_NO_PAREN, + options: [{style: 'never', assignment: true}], + parserOptions: parserOptions + }, { + code: DECLARATION_NO_PAREN, + options: [{style: 'never', declaration: true}], + parserOptions: parserOptions + }, { + code: RETURN_NO_PAREN, + options: [{style: 'never', return: true}], + parserOptions: parserOptions } ], @@ -219,6 +231,24 @@ ruleTester.run('jsx-wrap-multilines', rule, { parserOptions: parserOptions, options: [{assignment: true}], errors: [{message: 'Missing parentheses around multilines JSX'}] + }, { + code: ASSIGNMENT_PAREN, + output: ASSIGNMENT_NO_PAREN, + parserOptions: parserOptions, + options: [{style: 'never', assignment: true}], + errors: [{message: 'Parentheses around JSX are not allowed'}] + }, { + code: DECLARATION_PAREN, + output: DECLARATION_NO_PAREN, + parserOptions: parserOptions, + options: [{style: 'never', declaration: true}], + errors: [{message: 'Parentheses around JSX are not allowed'}] + }, { + code: RETURN_PAREN, + output: RETURN_NO_PAREN, + parserOptions: parserOptions, + options: [{style: 'never', return: true}], + errors: [{message: 'Parentheses around JSX are not allowed'}] } ] });