| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 | /** * @fileoverview Enforce newlines between operands of ternary expressions * @author Kai Cataldo */"use strict";const astUtils = require("./utils/ast-utils");//------------------------------------------------------------------------------// Rule Definition//------------------------------------------------------------------------------/** @type {import('../shared/types').Rule} */module.exports = {    meta: {        type: "layout",        docs: {            description: "Enforce newlines between operands of ternary expressions",            recommended: false,            url: "https://eslint.org/docs/rules/multiline-ternary"        },        schema: [            {                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: "whitespace"    },    create(context) {        const sourceCode = context.getSourceCode();        const option = context.options[0];        const multiline = option !== "never";        const allowSingleLine = option === "always-multiline";        //--------------------------------------------------------------------------        // Public        //--------------------------------------------------------------------------        return {            ConditionalExpression(node) {                const questionToken = sourceCode.getTokenAfter(node.test, astUtils.isNotClosingParenToken);                const colonToken = sourceCode.getTokenAfter(node.consequent, astUtils.isNotClosingParenToken);                const firstTokenOfTest = sourceCode.getFirstToken(node);                const lastTokenOfTest = sourceCode.getTokenBefore(questionToken);                const firstTokenOfConsequent = sourceCode.getTokenAfter(questionToken);                const lastTokenOfConsequent = sourceCode.getTokenBefore(colonToken);                const firstTokenOfAlternate = sourceCode.getTokenAfter(colonToken);                const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, firstTokenOfConsequent);                const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, firstTokenOfAlternate);                const hasComments = !!sourceCode.getCommentsInside(node).length;                if (!multiline) {                    if (!areTestAndConsequentOnSameLine) {                        context.report({                            node: node.test,                            loc: {                                start: firstTokenOfTest.loc.start,                                end: lastTokenOfTest.loc.end                            },                            messageId: "unexpectedTestCons",                            fix(fixer) {                                if (hasComments) {                                    return null;                                }                                const fixers = [];                                const areTestAndQuestionOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, questionToken);                                const areQuestionAndConsOnSameLine = astUtils.isTokenOnSameLine(questionToken, firstTokenOfConsequent);                                if (!areTestAndQuestionOnSameLine) {                                    fixers.push(fixer.removeRange([lastTokenOfTest.range[1], questionToken.range[0]]));                                }                                if (!areQuestionAndConsOnSameLine) {                                    fixers.push(fixer.removeRange([questionToken.range[1], firstTokenOfConsequent.range[0]]));                                }                                return fixers;                            }                        });                    }                    if (!areConsequentAndAlternateOnSameLine) {                        context.report({                            node: node.consequent,                            loc: {                                start: firstTokenOfConsequent.loc.start,                                end: lastTokenOfConsequent.loc.end                            },                            messageId: "unexpectedConsAlt",                            fix(fixer) {                                if (hasComments) {                                    return null;                                }                                const fixers = [];                                const areConsAndColonOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, colonToken);                                const areColonAndAltOnSameLine = astUtils.isTokenOnSameLine(colonToken, firstTokenOfAlternate);                                if (!areConsAndColonOnSameLine) {                                    fixers.push(fixer.removeRange([lastTokenOfConsequent.range[1], colonToken.range[0]]));                                }                                if (!areColonAndAltOnSameLine) {                                    fixers.push(fixer.removeRange([colonToken.range[1], firstTokenOfAlternate.range[0]]));                                }                                return fixers;                            }                        });                    }                } else {                    if (allowSingleLine && node.loc.start.line === node.loc.end.line) {                        return;                    }                    if (areTestAndConsequentOnSameLine) {                        context.report({                            node: node.test,                            loc: {                                start: firstTokenOfTest.loc.start,                                end: lastTokenOfTest.loc.end                            },                            messageId: "expectedTestCons",                            fix: fixer => (hasComments ? null : (                                fixer.replaceTextRange(                                    [                                        lastTokenOfTest.range[1],                                        questionToken.range[0]                                    ],                                    "\n"                                )                            ))                        });                    }                    if (areConsequentAndAlternateOnSameLine) {                        context.report({                            node: node.consequent,                            loc: {                                start: firstTokenOfConsequent.loc.start,                                end: lastTokenOfConsequent.loc.end                            },                            messageId: "expectedConsAlt",                            fix: (fixer => (hasComments ? null : (                                fixer.replaceTextRange(                                    [                                        lastTokenOfConsequent.range[1],                                        colonToken.range[0]                                    ],                                    "\n"                                )                            )))                        });                    }                }            }        };    }};
 |