Skip to content

Commit

Permalink
Update: fix parenthesized ternary expression indentation (fixes #8637) (
Browse files Browse the repository at this point in the history
#8649)

This updates the `indent` logic to correctly handle cases where the last two clauses of a ternary expression are on the same line.
  • Loading branch information
not-an-aardvark committed May 27, 2017
1 parent 4f2f9fc commit c4ac969
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 4 deletions.
46 changes: 42 additions & 4 deletions lib/rules/indent.js
Expand Up @@ -690,7 +690,7 @@ module.exports = {
const firstTokenOfPreviousElement = previousElement && getFirstToken(previousElement);

if (previousElement && sourceCode.getLastToken(previousElement).loc.start.line > startToken.loc.end.line) {
offsets.matchIndentOf(firstTokenOfPreviousElement, getFirstToken(elements[index]));
offsets.matchIndentOf(firstTokenOfPreviousElement, getFirstToken(element));
}
}
});
Expand Down Expand Up @@ -982,7 +982,7 @@ module.exports = {
ClassExpression: addClassIndent,

ConditionalExpression(node) {
const tokens = getTokensAndComments(node);
const firstToken = sourceCode.getFirstToken(node);

// `flatTernaryExpressions` option is for the following style:
// var a =
Expand All @@ -991,9 +991,47 @@ module.exports = {
// /*else*/ qiz ;
if (!options.flatTernaryExpressions ||
!astUtils.isTokenOnSameLine(node.test, node.consequent) ||
isFirstTokenOfStatement(tokens[0], node)
isFirstTokenOfStatement(firstToken, node)
) {
offsets.setDesiredOffsets(tokens, tokens[0], 1);
const questionMarkToken = sourceCode.getFirstTokenBetween(node.test, node.consequent, token => token.type === "Punctuator" && token.value === "?");
const colonToken = sourceCode.getFirstTokenBetween(node.consequent, node.alternate, token => token.type === "Punctuator" && token.value === ":");

const consequentTokens = sourceCode.getTokensBetween(questionMarkToken, colonToken, { includeComments: true });
const alternateTokens = sourceCode.getTokensAfter(colonToken, token => token.range[1] <= node.range[1]);

offsets.setDesiredOffset(questionMarkToken, firstToken, 1);
offsets.setDesiredOffset(colonToken, firstToken, 1);

offsets.setDesiredOffset(consequentTokens[0], firstToken, 1);

/*
* The alternate and the consequent should usually have the same indentation.
* If they share part of a line, align the alternate against the first token of the consequent.
* This allows the alternate to be indented correctly in cases like this:
* foo ? (
* bar
* ) : ( // this '(' is aligned with the '(' above, so it's considered to be aligned with `foo`
* baz // as a result, `baz` is offset by 1 rather than 2
* )
*/
if (consequentTokens[consequentTokens.length - 1].loc.end.line === alternateTokens[0].loc.start.line) {
offsets.matchIndentOf(consequentTokens[0], alternateTokens[0]);
} else {

/**
* If the alternate and consequent do not share part of a line, offset the alternate from the first
* token of the conditional expression. For example:
* foo ? bar
* : baz
*
* If `baz` were aligned with `bar` rather than being offset by 1 from `foo`, `baz` would end up
* having no expected indentation.
*/
offsets.setDesiredOffset(alternateTokens[0], firstToken, 1);
}

offsets.setDesiredOffsets(consequentTokens, consequentTokens[0], 0);
offsets.setDesiredOffsets(alternateTokens, alternateTokens[0], 0);
}
},

Expand Down
58 changes: 58 additions & 0 deletions tests/lib/rules/indent.js
Expand Up @@ -4410,6 +4410,26 @@ ruleTester.run("indent", rule, {
="number"
/>
`
},
{
code: unIndent`
foo ? (
bar
) : (
baz
)
`
},
{
code: unIndent`
foo ? (
<div>
</div>
) : (
<span>
</span>
)
`
}
],

Expand Down Expand Up @@ -8423,6 +8443,44 @@ ruleTester.run("indent", rule, {
/>
`,
errors: expectedErrors([4, 8, 4, "Punctuator"])
},
{
code: unIndent`
foo ? (
bar
) : (
baz
)
`,
output: unIndent`
foo ? (
bar
) : (
baz
)
`,
errors: expectedErrors([[4, 4, 8, "Identifier"], [5, 0, 4, "Punctuator"]])
},
{
code: unIndent`
foo ? (
<div>
</div>
) : (
<span>
</span>
)
`,
output: unIndent`
foo ? (
<div>
</div>
) : (
<span>
</span>
)
`,
errors: expectedErrors([[5, 4, 8, "Punctuator"], [6, 4, 8, "Punctuator"], [7, 0, 4, "Punctuator"]])
}
]
});

0 comments on commit c4ac969

Please sign in to comment.