Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add option style to jsx-wrap-multilines rule #1039

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion docs/rules/jsx-wrap-multilines.md
Original file line number Diff line number Diff line change
@@ -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).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a * here won't translate to a footnote below - I think perhaps leaving this paragraph alone, and adding a second paragraph that describes "never", would be better.


* 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"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think adding an object property is the best schema here - I think we want to be able to do:

["error", "never", {
  …
}]


["error", "always", {
  …
}]


["error", { // implies "always"
  …
}]

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah.. agree, I'll try to do it tomorrow, with the docs stuff.

"assignment": bool, // default true
"declaration": bool, // default true
"return": bool, // default true
}]
```

The following patterns are considered warnings:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we'll need to add "considered warnings" and "not considered warnings" examples for the "never" option as well.


```js
Expand Down
40 changes: 32 additions & 8 deletions lib/rules/jsx-wrap-multilines.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ var has = require('has');
// ------------------------------------------------------------------------------

var DEFAULTS = {
style: 'always',
declaration: true,
assignment: true,
return: true
Expand All @@ -32,6 +33,10 @@ module.exports = {
schema: [{
type: 'object',
properties: {
style: {
type: 'string',
enum: ['always', 'never']
},
declaration: {
type: 'boolean'
},
Expand All @@ -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);
Expand All @@ -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',
Expand All @@ -77,22 +91,32 @@ 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];
}

// --------------------------------------------------------------------------
// Public
// --------------------------------------------------------------------------

return {

VariableDeclarator: function(node) {
if (!isEnabled('declaration')) {
return;
Expand Down
30 changes: 30 additions & 0 deletions tests/lib/rules/jsx-wrap-multilines.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
],

Expand Down Expand Up @@ -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'}]
}
]
});