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
Rule Proposal: multiline-ternary #6066
Comments
I can champion this and write the rule when we get the details ironed out. |
Isn't this already covered by operator-linebreak? (http://eslint.org/docs/rules/operator-linebreak) |
No.
Honestly, I'm not sure this is proper for core. |
@mysticatea Curious about why you think this might not belong in core. Seems like it's general enough to me - would love to hear your thoughts |
Merely I'm not sure the purpose of this rule. When I'm using ternary expressions, there are 3 kind situations. // shorter.
let foo = (a > 0 ? b : c);
// longer.
let foo = (
this_is_a_long_expression > 0 ?
this_is_a_long_expression2 :
this_is_a_long_expression3
);
// multiple
let foo = (
a === A ? 1 :
a === B ? 2 :
a === C ? 3 :
a === D ? 4 :
/* else */ 0
); If I apply this rule to that code: // never
let foo = (a > 0 ? b : c);
let foo = (this_is_a_long_expression > 0 ? this_is_a_long_expression2 : this_is_a_long_expression3);
let foo = (a === A ? 1 : a === B ? 2 : a === C ? 3 : a === D ? 4 : 0);
// always
let foo = (
a > 0 ?
b :
c
);
let foo = (
this_is_a_long_expression > 0 ?
this_is_a_long_expression2 :
this_is_a_long_expression3
);
let foo = (
a === A ?
1 :
a === B ?
2 :
a === C ?
3 :
a === D ?
4 :
0
); Well, the "multiple" case may be not common. |
I see - thanks for explaining. I personally don't think I would use the {
"multiline-ternary": [
"error",
"always" or "never" or "when-needed", { maxExpressionLength: 40 }
]
} Example: // when-needed, { maxExpressionLength: 12 }
let foo = (a > 0 ? b : c);
let foo = (
this_is_a_long_expression > 0 ?
a :
this_is_a_long_expression3
); "when-needed" isn't the right name, but hopefully it gets my point across. This would allow for parity with the JSCS rule while giving users a little more control. I generally follow the "when-needed" pattern when I'm writing my own code - if the expressions are longer I break it into multiple lines, but otherwise like to keep it on one. |
I got it. I'd like to use the end column of a ternary expression (after line breaks are removed) rather than the length of a ternary expression, but I'm not sure it's safe since it's changeable in multipass autofix. |
@mysticatea Not sure I'm following - sorry - could you show me an example of what you mean? I'm happy to get started on this when we decide what this should look like and it gets accepted :) |
I'm sorry. This is an example. /*eslint multiline-ternary: [error, {minColumn: 50}]*/
// 1 2 3 4 5
// 345678901234567890123456789012345678901234567890
let foo = condition > 0 ? value1 : value2; // GOOD, column is 40.
function foo(cond) {
if (cond) {
for (let i = 0; i < 10; ++i) {
// 1 2 3 4 5 6
// 3456789012345678901234567890123456789012345678901234567890
let longNameVariable = (a > 0 ? value1 : value2); // BAD, column is 58.
}
}
} |
Thanks - I think I understand! I think you're right, that makes more sense than testing the individual expressions - allows you to configure it to the same value as |
Yes, |
Maybe we could check for the linebreak type and make sure we only count it as one character? |
Maybe we need the configuration of spacing rules in order to count column/length... :( // 1 2 3 4 5
// 345678901234567890123456789012345678901234567890
let longNameVariable = (a > 0 ? value1 : value2); // This is 46
let longNameVariable = (a > 0 ? // This is 46?
value1 :
value2);
let longNameVariable = (a > 0 ? // This is 46?
value1 :
value2);
let longNameVariable = (a>0?value1:value2); // This is...
// In a case that there are line breaks in expression...
let longNameVariable = (a > 0 ?
value1 + // should not this line break be removed by this rule?
"foo" +
"bar" :
value2);
let longNameVariable = (a > 0 ? value1 +
"foo" +
"bar" : value2);
// In a nested case...
let longNameVariable = (a > 0 ? value1 : b > 0 ? value2 : value3);
let longNameVariable = (a > 0 ?
value1 :
b > 0 ?
value2 :
value3);
let longNameVariable = (a > 0 ?
value1 :
b > 0 ? value2 : value3); |
Would it be worth it to make this rule now as we've talked about and just not do auto-fixing yet? Sounds like we need to figure out autofixing with newlines across the project, not just here. Some examples, off the top of my head: |
If we use length/column in an option, that info is needed to distinguish whether line breaks are needed or not. // 1 2 3 4 5
// 345678901234567890123456789012345678901234567890
let longNameVariable = (a > 0 ? // Is this over 45 or not?
value1 :
value2);
let longNameVariable = (a > 0 ? value1 : value2); // This is 46
let longNameVariable = (a > 0 ?value1 :value2); // This is 44 Ah... |
Hm, I see. Any ideas @eslint/eslint-team? I can get started on this as soon as we hammer the details out :) |
I think we should leave aside the discussion about length based multiline. Regarding the original rule proposal, |
@alberto why do you think we should not include a line length-based option? Curious since in my mind this allows us to have feature parity with the JSCS rules while having an option that allows for parity with max-len. @mysticatea I think it makes sense for the option to only warn if the entire ternary is on one line and the length is too long. It could be calculated similarly to max-len then. If it's already a multi-line ternary then this option will ignore it and max-len should catch the individual lines. I like the simplicity of it. |
I think we can drastically simplify this discussion by only implementing the "always" portion of this rule. If we're concerned about "never" conflicting with "max-len", consider that JSCS likely only implemented that option because in general we always provided both rules for consistency sake (likely a mistake there). Either way, we can provide the rule, knowing it can conflict with |
@mikesherov The insight into why JSCS had both is really helpful - if that's the case, I'm totally with you on just implementing "always". I'm realizing the length-based option I outlined in my last comment has morphed into really being the same thing as turning off this proposed rule and turning on TL;DR I'm 👍 for @mikesherov's suggestion |
@kaicataldo because the priority is JSCS compatibility and there is some uncertainty in the value that option provides when @mikesherov since we decided we don't want to deprecate options in existing rules, I think it would be preferable to only add |
Seems reasonable to me 👍. |
I don't currently need tooling to enforce this, so feel free not to implement it -- but my personal style uses |
Starting working on this and realized I have some questions:
|
Just my two cents- I think auto-fix on this rule will create more problems than it solves. One other thought: Does JSCS attempt to fix this? |
@platinumazure I agree with you, and no, I don't think the JSCS rule fixes this |
From requireMultiLineTernary and disallowMultiLineTernary.
This rule will require/disallow multiline conditional expressions.
"always"
(default) - Requires a line break for each operator (?
and:
)."never"
- Disallow line breaks in a conditional expression.The text was updated successfully, but these errors were encountered: