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: continuation-linebreak #9510

Closed
1 of 4 tasks
sharmilajesupaul opened this issue Oct 24, 2017 · 11 comments
Closed
1 of 4 tasks

New Rule: continuation-linebreak #9510

sharmilajesupaul opened this issue Oct 24, 2017 · 11 comments
Labels
archived due to age This issue has been archived; please open a new issue for any further discussion evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion feature This change adds a new feature to ESLint rule Relates to ESLint's core rules

Comments

@sharmilajesupaul
Copy link
Contributor

Please describe what the rule should do:

This rule sets a strict style guideline for multiline arrow functions and expression statements; it can be customized to require or disallow a line break after => or =.

Ending a line with => or = causes a readability issue by ambiguating what the assignment or function body contains. Moving the function body or second line of assignment inline beside => or = should fix this issue.

This rule can be auto-fixed by bumping the second line to be inline beside => or =. This can also be fixed by wrapping the multiline body in parentheses (see "multilineParens": true option).

Future Rule Extension: Add a guideline for object's that have keys and values multiple lines i.e. that end a line with a :.

Potential Options:

Array options:

  • ["always", { "multilineParens": false }] - (default) require that a an assignment or arrow function must always have a line break i.e. always break on = or =>. This option takes an additional object parameter with the property multilineParens. Setting "multilineParens": true would require that multiline statements be wrapped in parentheses.

  • ["never", { "multilineParens": false }] - requires that there should never be a linebreak in the middle of a continuation, i.e. never break on a = or =>. This takes an additional object parameter with the property multilineParens. Setting "multilineParens": true would require that multiline statements be wrapped in parentheses.

  • ["conditional", { "multilineParens": false, "maxLength": 80 }] - requires that statements shorter than the maxLength should be inline and statements that are longer than the maxLength need to be split up on multiple lines. This option takes an additional object parameter with the properties multilineParens and maxLength. "multilineParens": true would require wrapping rule violations in parentheses if they exceed the maxLength and inline the continuation when the line length is below the maxLength. The maxLength property can have a default value of 80.

What category of rule is this? (place an "X" next to just one item)

  • Enforces code style
  • Warns about a potential error
  • Suggests an alternate way of doing something
  • Other (please specify:)

Provide 2-3 code examples that this rule will warn about:

Option: "always", { "multilineParens": false }

These options are compatible with Prettier's auto formatting

// bad
x => "foo";

// bad
(x) => {
  return foo;
}

// bad
const foo = bar
  ? 1
  : 2;

// bad
const foo = "bar";

// good
x =>
  "foo";

// good
(x) =>
  {
    return "foo";
  }

// good
const foo =
  "bar";

// good
const foo =
  bar
  ? 1
  : 2;

Option: "always", { "multilineParens": true }

// bad
x => "foo";

// good
x => (
  "foo"
);

Option: "never", { "multilineParens": false }

// bad
x =>
  "foo";

// bad
(x) =>
  {
    return "foo";
  }

// bad
const foo =
  "bar";

// bad
const foo =
  bar
  ? 1
  : 2;

// good
x => "foo";

// good
(x) => {
  return foo;
}

// good
const foo = bar
  ? 1
  : 2;

// good
const foo = "bar";

Option: "never", { "multilineParens": true }

// bad
x =>
  "foo";

// good
x => (
  "foo"
);

Option: "conditional", { "multilineParens": false, "maxLength": 20 }

default maxLength can be 80, I'm using 20 for demonstrative purposes

// bad
x => "longLongName";

// bad
x =>
  "foo";

// bad
const foo =
  "bar";

// bad
const foo = bar ? 1 : "longLongName";

// good
x =>
  "longLongName";

// good
x => "foo";

// good
const foo = "bar";

// good
const foo = bar
  ? 1
  : "longLongName";

Option: "conditional", { "multilineParens": true, "maxLength": 20 }

default maxLength can be 80, I'm using 20 for demonstrative purposes

// bad
x => "longLongName";

// good
x => (
  "longLongName";
);

Why should this rule be included in ESLint (instead of a plugin)?

This rule is very wide-reaching and can improve overall code style.

@eslintbot eslintbot added the triage An ESLint team member will look at this issue soon label Oct 24, 2017
@platinumazure
Copy link
Member

Is this something that is, or could be, covered by operator-linebreak?

@ljharb
Copy link
Sponsor Contributor

ljharb commented Oct 24, 2017

@platinumazure => isn't an operator - does operator-linebreak check =?

@not-an-aardvark
Copy link
Member

=> was discussed in #6067 (comment) as part of non-block-statement-body-position, but we decided not to include it in that rule. I don't think operator-linebreak currently checks =, but I think it would be reasonable for it to do so.

@ljharb
Copy link
Sponsor Contributor

ljharb commented Oct 24, 2017

As long as we can get both of these patterns checked and autofixed in the very near term, then that solves @airbnb's use cases - we don't have any strong preference whether it's a separate rule or enhancements to existing rules :-)

@not-an-aardvark not-an-aardvark added evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion feature This change adds a new feature to ESLint rule Relates to ESLint's core rules and removed triage An ESLint team member will look at this issue soon labels Oct 25, 2017
@not-an-aardvark
Copy link
Member

A few thoughts after reading this again:

  • I don't think this is doing the same thing as operator-linebreak -- operator-linebreak makes reports based on where a linebreak is when there is a linebreak, but this rule would make assertions about whether a linebreak should be present.

  • Would this rule cover arrow functions with block bodies? Based on the examples you've provided, it seems like it would cover that, but it seems like that behavior would conflict with the brace-style rule, which already checks whether there should be linebreaks before arrow function blocks.

  • I'm confused about why this rule specifically concerns = and =>, but not operators like +. I'm also not sure I understand the readability issue described at the top -- I can see why it would be good to format code like this consistently, but I don't see why ending a line with => would be less readable. Could you clarify what the readability issue is? (This is important because I think it would affect the scope of the rule -- if the readability issue is specific to arrow functions and assignments, then it would probably be better to make the rule only cover those two types of syntax. If this is just needed for consistent formatting, then it could be better to include other operators as well.)

  • Regarding the maxLength option: In the past, we've generally avoided adding options that switch behavior based on the text length of a piece of code -- see Force objects/arrays/ArgumentLists/FormalParameters that can fit on one line, onto one line #7526 and 'max-len' conflict with 'function-paren-newline' #9411 for the reasoning.

  • As long as we can get both of these patterns checked and autofixed in the very near term, then that solves @airbnb's use cases

    If timing is a priority and you want to use this internally in the short term, it could be better to implement this as a custom rule. As you've seen, we occasionally spend a significant amount of time on the design of core rules because they need to be maintained and supported indefinitely. Presumably, internal custom rules would have less strict backwards-compatibility requirements, which could make it possible to design them more quickly and without as much bikeshedding.

@ljharb
Copy link
Sponsor Contributor

ljharb commented Oct 25, 2017

this rule would make assertions about whether a linebreak should be present.

agreed.

Could you clarify what the readability issue is?

const x = y =>
  something;

We find this less readable because it's not as apparent that it's a continuation; whereas in:

const x = y => (
  something
);

the parens make it clear.

I'm confused about why this rule specifically concerns = and =>, but not operators like +

= is an operator, but => is not, so I'm not sure why there's a conflation with +. That said, there are a number of places where this kind of conceptual rule would apply, which is partially why a new rule might make sense - because then it provides an extension point for other constructs to be handled, including arbitrary binary operators. However, => and = cover the 80/20 use case for us.


Certainly in the short term we'll implement it internally :-) however the goal is to include this in our public styleguide, so that won't suffice in the medium term.

If maxLength isn't viable (and thus "conditional" isn't viable), I think we can still get by with ['never', { multilineParens: true }] - @sharmilajesupaul, can you confirm?

@sharmilajesupaul
Copy link
Contributor Author

sharmilajesupaul commented Oct 25, 2017

yup @ljharb - ['never', { multilineParens: true }] should give us what we want.
It would require:

const x = y => something;
// or 
const x = y => (
  something
);

and warn on:

const x = y =>
  something;

We added maxLength just to make this rule customizable enough to enforce a multiline statement when the line exceeds a certain length. But it certainly isn't necessary.

edit: missing ;

@ljharb
Copy link
Sponsor Contributor

ljharb commented Oct 25, 2017

@not-an-aardvark @platinumazure it seems like the two paths forward are either:

  1. this rule, without the "conditional" option
  2. add => support to non-block-statement-body-position and = support to operator-linebreak

Are one of those palatable?

@ilyavolodin
Copy link
Member

In general I'm 👍 for the described scenarios (btw, thanks a lot for providing such clear rule request, it really helps). I'm just not sure about conflating arrows and equal operator into the same rule. I understand the goal, just not sure it makes sense when you are just looking through the list of rules. Would operator-linebreak: ['error', { "overrides": { "=": "none" } }] cover your equal operator requirements? Or do you want the expression to be always wrapped into parentheses? If it covers what you want, then I would suggest creating a separate rule arrow-linebreak without conditional option as described above (conditional can always be added later if needed).

@ljharb
Copy link
Sponsor Contributor

ljharb commented Oct 25, 2017

I think that does cover what we want; it'd be ideal to include handling of multiline + parens, but being able to autofix to one line, and manually fix to multiline + parens, is sufficient for =.

sharmilajesupaul added a commit to sharmilajesupaul/eslint that referenced this issue Nov 15, 2017
…Fixes: eslint#9510)

This update nonblock-statement-body-position to also warn on arrow functions. This is related to the issue: eslint#9510.
sharmilajesupaul added a commit to sharmilajesupaul/eslint that referenced this issue Nov 15, 2017
…le (Fixes: eslint#9510)

This update nonblock-statement-body-position to also warn on arrow functions. This is related to the issue: eslint#9510.
sharmilajesupaul added a commit to sharmilajesupaul/eslint that referenced this issue Nov 15, 2017
…le (Refs: eslint#9510)

This update nonblock-statement-body-position to also warn on arrow functions. This is related to the issue: eslint#9510.
sharmilajesupaul added a commit to sharmilajesupaul/eslint that referenced this issue Nov 15, 2017
…slint#9510)

This update nonblock-statement-body-position to also warn on arrow functions. This is related to the issue: eslint#9510.
sharmilajesupaul added a commit to sharmilajesupaul/eslint that referenced this issue Nov 15, 2017
…#9510)

This update nonblock-statement-body-position to also warn on arrow functions.
This is related to the issue: eslint#9510.
sharmilajesupaul added a commit to sharmilajesupaul/eslint that referenced this issue Nov 15, 2017
…#9510)

This update nonblock-statement-body-position to also warn on arrow functions.
This is related to the issue: eslint#9510.
sharmilajesupaul added a commit to sharmilajesupaul/eslint that referenced this issue Nov 15, 2017
Adds a new rule that enforces consistency of arrow function bodies
that contain an implicit return.
sharmilajesupaul added a commit to sharmilajesupaul/eslint that referenced this issue Nov 15, 2017
Adds a new rule that enforces consistency of arrow function bodies
that contain an implicit return.
sharmilajesupaul added a commit to sharmilajesupaul/eslint that referenced this issue Nov 20, 2017
Adds a new rule that enforces consistency of arrow function bodies
that contain an implicit return.
not-an-aardvark pushed a commit that referenced this issue Nov 26, 2017
* New: Adds implicit-arrow-linebreak rule (refs #9510)

Adds a new rule that enforces consistency of arrow function bodies
that contain an implicit return.

* Docs: Use "implicit-arrow-linebreak" consistently

* Chore: Use name "implicit-arrow-linebreak"
@sharmilajesupaul
Copy link
Contributor Author

Closing this since we can achieve the behavior we need by enabling operator-linebreak with the configuration mentioned by @ilyavolodin in #9510 (comment) in conjunction with implicit-arrow-linebreak.

Thanks for the help!

@eslint-deprecated eslint-deprecated bot locked and limited conversation to collaborators Jun 18, 2018
@eslint-deprecated eslint-deprecated bot added the archived due to age This issue has been archived; please open a new issue for any further discussion label Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
archived due to age This issue has been archived; please open a new issue for any further discussion evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion feature This change adds a new feature to ESLint rule Relates to ESLint's core rules
Projects
None yet
Development

No branches or pull requests

6 participants