diff --git a/lib/rules/multiline-ternary.js b/lib/rules/multiline-ternary.js index 1df90b6feb83..1dbfb0f67ace 100644 --- a/lib/rules/multiline-ternary.js +++ b/lib/rules/multiline-ternary.js @@ -27,12 +27,15 @@ module.exports = { enum: ["always", "always-multiline", "never"] } ], + messages: { expectedTestCons: "Expected newline between test and consequent of ternary expression.", expectedConsAlt: "Expected newline between consequent and alternate of ternary expression.", unexpectedTestCons: "Unexpected newline between test and consequent of ternary expression.", unexpectedConsAlt: "Unexpected newline between consequent and alternate of ternary expression." - } + }, + + fixable: "code" }, create(context) { @@ -52,10 +55,61 @@ module.exports = { * @returns {void} * @private */ - function reportError(node, parentNode, expected) { + function reportSingleLineError(node, parentNode, expected) { + context.report({ + node, + messageId: `${expected ? "expected" : "unexpected"}${node === parentNode.test ? "TestCons" : "ConsAlt"}`, + fix: fixer => ([ + !astUtils.isTokenOnSameLine(parentNode.test, parentNode.consequent) && + fixer.replaceTextRange( + [ + parentNode.test.range[1], + parentNode.consequent.range[0] + ], + " ? " + ), + !astUtils.isTokenOnSameLine(parentNode.consequent, parentNode.alternate) && + fixer.replaceTextRange( + [ + parentNode.consequent.range[1], + parentNode.alternate.range[0] + ], + " : " + ) + ]) + }); + } + + /** + * Tests whether node is preceded by supplied tokens + * @param {ASTNode} node node to check + * @param {ASTNode} parentNode parent of node to report + * @param {boolean} expected whether newline was expected or not + * @returns {void} + * @private + */ + function reportMultilineError(node, parentNode, expected) { context.report({ node, - messageId: `${expected ? "expected" : "unexpected"}${node === parentNode.test ? "TestCons" : "ConsAlt"}` + messageId: `${expected ? "expected" : "unexpected"}${node === parentNode.test ? "TestCons" : "ConsAlt"}`, + fix: fixer => ([ + astUtils.isTokenOnSameLine(parentNode.test, parentNode.consequent) && + fixer.replaceTextRange( + [ + parentNode.test.range[1], + parentNode.consequent.range[0] + ], + "\n? " + ), + astUtils.isTokenOnSameLine(parentNode.consequent, parentNode.alternate) && + fixer.replaceTextRange( + [ + parentNode.consequent.range[1], + parentNode.alternate.range[0] + ], + "\n: " + ) + ]) }); } @@ -70,11 +124,11 @@ module.exports = { if (!multiline) { if (!areTestAndConsequentOnSameLine) { - reportError(node.test, node, false); + reportSingleLineError(node.test, node, false); } if (!areConsequentAndAlternateOnSameLine) { - reportError(node.consequent, node, false); + reportSingleLineError(node.consequent, node, false); } } else { if (allowSingleLine && node.loc.start.line === node.loc.end.line) { @@ -82,11 +136,11 @@ module.exports = { } if (areTestAndConsequentOnSameLine) { - reportError(node.test, node, true); + reportMultilineError(node.test, node, true); } if (areConsequentAndAlternateOnSameLine) { - reportError(node.consequent, node, true); + reportMultilineError(node.consequent, node, true); } } }