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"
- )
- )))
- });
- }
- }
- }
- };
- }
- };
|