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

New rule: jsx-one-expression-per-line #1497

Merged
merged 14 commits into from Oct 30, 2017

Conversation

TSMMark
Copy link
Contributor

@TSMMark TSMMark commented Oct 25, 2017

From issue #1491.

Tested against a small react-native app with 50-100 components and it works great.

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

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

Thanks, this seems pretty solid.

I gather that you're choosing an indent of zero, so that the indent rule can correct it properly?

@jseminck
Copy link
Contributor

There are only tests for components. Should it also warn on <div><span>Hello World</span></div> ?

@TSMMark
Copy link
Contributor Author

TSMMark commented Oct 25, 2017

I gather that you're choosing an indent of zero, so that the indent rule can correct it properly?

That's right.

There are only tests for components. Should it also warn on <div><span>Hello World</span></div> ?

Not sure why that would make a difference, but I added a case for ya.

].join('\n'),
output: [
'<div>',
' <span />foo',
Copy link
Member

Choose a reason for hiding this comment

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

If the lack of whitespace before "foo" is important, then it's just as important after "foo" - meaning, this example can't be autofixed.

However,

<div>
  <span /> foo <input />
</div>

definitely should become:

<div>
  <span />
  foo
  <input />
</div>

Copy link
Contributor Author

@TSMMark TSMMark Oct 25, 2017

Choose a reason for hiding this comment

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

@ljharb I believe white space in jsx is differnt from HTML and in your example the two jsx snippets are actually rendered differently. foo in the first snippet will be rendered to the DOM with a whitespace on either side, while foo in the second snippet will have no whitespace.

However, even if I'm correct the rule still does need to be patched. Currently, the autofix does change the rendered whitespace under certain conditions, which is obviously unacceptable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Using curlies and transforming into a string literal with spacing on either side seems the most accurate. Is this acceptible?

<div>
  <span />
  {' foo '}
  <input />
</div>

Copy link
Member

Choose a reason for hiding this comment

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

Sure, that'd be great!

As long as the autofix is not changing the resulting whitespace that's rendered, we're good.

@TSMMark
Copy link
Contributor Author

TSMMark commented Oct 25, 2017

Hey @ljharb I spec'd out what I think is the best approach for handling white space. Basically, it comes down to not handling it and letting the user fix each case on their own. ptal if you could: 799dfa6

If y'all agree I'll implement this behavior in the next couple days

@ljharb
Copy link
Member

ljharb commented Oct 25, 2017

@TSMMark i think we'd need to either add an option, or have this be the default, so that the things that aren't autofixable aren't warned.

@TSMMark
Copy link
Contributor Author

TSMMark commented Oct 26, 2017

For the record, I am attempting to handle all autofix cases and it is proving rather difficult.

Edit: Just discovered isSpaceBetweenTokens and it looks like this might be exactly what I need to make this work.

@TSMMark
Copy link
Contributor Author

TSMMark commented Oct 27, 2017

@ljharb Well, I had to throw everything out and start over, but now we can handle all cases! 😌

How's it look?

Now that we handle all nodes instead of only React elements, this name
seems more fitting.
@TSMMark TSMMark changed the title New rule: jsx-one-element-per-line New rule: jsx-one-expression-per-line Oct 27, 2017
Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

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

Looking much better :-)

].join('\n'),
output: [
'<div>',
' foo ',
Copy link
Member

Choose a reason for hiding this comment

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

this can cause issues due to rules that strip trailing spaces; i think this needs to remain as foo {"bar"}, untouched.

Copy link
Contributor Author

@TSMMark TSMMark Oct 28, 2017

Choose a reason for hiding this comment

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

foo and {"bar"} are 2 different expressions and I don't want them on the same line. JSX parser ignores trailing spaces such as these, however, I'll see if I can kill them, as per #1497 (comment)

Copy link
Member

Choose a reason for hiding this comment

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

right - but the jsx parser doesn't ignore the space in between foo {"bar" } - so to make it the same, with an autofix, you'd need:

foo
{' '}
{'bar'}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, if you look on the next line 117 you will see {\' \'}

Copy link
Contributor Author

@TSMMark TSMMark Oct 28, 2017

Choose a reason for hiding this comment

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

It results in the same output after JSX parsing. I am following the guidelines:

Since all rules are run again after the initial round of fixes is applied, it’s not necessary for a rule to check whether the code style of a fix will cause errors to be reported by another rule.

https://eslint.org/docs/developer-guide/working-with-rules#applying-fixes

The trailing space in the output foo is inconsequential. Its only impact is offending no-trailing-spaces, which, as stated in the guide, is not our concern here.

].join('\n'),
output: [
'<div>',
' {"foo"} ',
Copy link
Member

Choose a reason for hiding this comment

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

this trailing space should be removed, if the space on the next line is being explicitly preserved?

Copy link
Contributor Author

@TSMMark TSMMark Oct 28, 2017

Choose a reason for hiding this comment

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

JSX parser already ignores trailing spaces, and no-trailing-spaces will chop them off anyway... but let me see if I can get rid of them. My thought process was the JSX output is identical so I would not need to handle them

Copy link
Member

Choose a reason for hiding this comment

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

i agree that no-trailing-spaces could do the cleanup, but it seems easy enough to .trim() any newly autofixed lines :-)

Copy link
Contributor Author

@TSMMark TSMMark Oct 28, 2017

Choose a reason for hiding this comment

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

See latest commit, best I can do right now. As you said, this does trim the newly autofixed nodes; however, it does not handle cases where the 'Literal' node is the first node on the line because it does not need to be placed on a new line, requiring no report/fix for that node.

Example:

https://github.com/Vydia/eslint-plugin-react/blob/1344f1dad2478d15a378d681128206bf969c733b/tests/lib/rules/jsx-one-expression-per-line.js#L714

].join('\n'),
output: [
'<Text style={styles.foo}>',
'{ bar } ',
Copy link
Member

Choose a reason for hiding this comment

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

also here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

None yet

5 participants