]> git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/multiline-ternary.js
import and build new upstream release 7.2.0
[pve-eslint.git] / eslint / lib / rules / multiline-ternary.js
1 /**
2 * @fileoverview Enforce newlines between operands of ternary expressions
3 * @author Kai Cataldo
4 */
5
6 "use strict";
7
8 const astUtils = require("./utils/ast-utils");
9
10 //------------------------------------------------------------------------------
11 // Rule Definition
12 //------------------------------------------------------------------------------
13
14 module.exports = {
15 meta: {
16 type: "layout",
17
18 docs: {
19 description: "enforce newlines between operands of ternary expressions",
20 category: "Stylistic Issues",
21 recommended: false,
22 url: "https://eslint.org/docs/rules/multiline-ternary"
23 },
24
25 schema: [
26 {
27 enum: ["always", "always-multiline", "never"]
28 }
29 ],
30 messages: {
31 expectedTestCons: "Expected newline between test and consequent of ternary expression.",
32 expectedConsAlt: "Expected newline between consequent and alternate of ternary expression.",
33 unexpectedTestCons: "Unexpected newline between test and consequent of ternary expression.",
34 unexpectedConsAlt: "Unexpected newline between consequent and alternate of ternary expression."
35 }
36 },
37
38 create(context) {
39 const option = context.options[0];
40 const multiline = option !== "never";
41 const allowSingleLine = option === "always-multiline";
42 const sourceCode = context.getSourceCode();
43
44 //--------------------------------------------------------------------------
45 // Public
46 //--------------------------------------------------------------------------
47
48 return {
49 ConditionalExpression(node) {
50 const questionToken = sourceCode.getTokenAfter(node.test, astUtils.isNotClosingParenToken);
51 const colonToken = sourceCode.getTokenAfter(node.consequent, astUtils.isNotClosingParenToken);
52
53 const firstTokenOfTest = sourceCode.getFirstToken(node);
54 const lastTokenOfTest = sourceCode.getTokenBefore(questionToken);
55 const firstTokenOfConsequent = sourceCode.getTokenAfter(questionToken);
56 const lastTokenOfConsequent = sourceCode.getTokenBefore(colonToken);
57 const firstTokenOfAlternate = sourceCode.getTokenAfter(colonToken);
58
59 const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, firstTokenOfConsequent);
60 const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, firstTokenOfAlternate);
61
62 if (!multiline) {
63 if (!areTestAndConsequentOnSameLine) {
64 context.report({
65 node: node.test,
66 loc: {
67 start: firstTokenOfTest.loc.start,
68 end: lastTokenOfTest.loc.end
69 },
70 messageId: "unexpectedTestCons"
71 });
72 }
73
74 if (!areConsequentAndAlternateOnSameLine) {
75 context.report({
76 node: node.consequent,
77 loc: {
78 start: firstTokenOfConsequent.loc.start,
79 end: lastTokenOfConsequent.loc.end
80 },
81 messageId: "unexpectedConsAlt"
82 });
83 }
84 } else {
85 if (allowSingleLine && node.loc.start.line === node.loc.end.line) {
86 return;
87 }
88
89 if (areTestAndConsequentOnSameLine) {
90 context.report({
91 node: node.test,
92 loc: {
93 start: firstTokenOfTest.loc.start,
94 end: lastTokenOfTest.loc.end
95 },
96 messageId: "expectedTestCons"
97 });
98 }
99
100 if (areConsequentAndAlternateOnSameLine) {
101 context.report({
102 node: node.consequent,
103 loc: {
104 start: firstTokenOfConsequent.loc.start,
105 end: lastTokenOfConsequent.loc.end
106 },
107 messageId: "expectedConsAlt"
108 });
109 }
110 }
111 }
112 };
113 }
114 };