.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / 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
31         messages: {
32             expectedTestCons: "Expected newline between test and consequent of ternary expression.",
33             expectedConsAlt: "Expected newline between consequent and alternate of ternary expression.",
34             unexpectedTestCons: "Unexpected newline between test and consequent of ternary expression.",
35             unexpectedConsAlt: "Unexpected newline between consequent and alternate of ternary expression."
36         },
37
38         fixable: "whitespace"
39     },
40
41     create(context) {
42         const sourceCode = context.getSourceCode();
43         const option = context.options[0];
44         const multiline = option !== "never";
45         const allowSingleLine = option === "always-multiline";
46
47         //--------------------------------------------------------------------------
48         // Public
49         //--------------------------------------------------------------------------
50
51         return {
52             ConditionalExpression(node) {
53                 const questionToken = sourceCode.getTokenAfter(node.test, astUtils.isNotClosingParenToken);
54                 const colonToken = sourceCode.getTokenAfter(node.consequent, astUtils.isNotClosingParenToken);
55
56                 const firstTokenOfTest = sourceCode.getFirstToken(node);
57                 const lastTokenOfTest = sourceCode.getTokenBefore(questionToken);
58                 const firstTokenOfConsequent = sourceCode.getTokenAfter(questionToken);
59                 const lastTokenOfConsequent = sourceCode.getTokenBefore(colonToken);
60                 const firstTokenOfAlternate = sourceCode.getTokenAfter(colonToken);
61
62                 const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, firstTokenOfConsequent);
63                 const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, firstTokenOfAlternate);
64
65                 const hasComments = !!sourceCode.getCommentsInside(node).length;
66
67                 if (!multiline) {
68                     if (!areTestAndConsequentOnSameLine) {
69                         context.report({
70                             node: node.test,
71                             loc: {
72                                 start: firstTokenOfTest.loc.start,
73                                 end: lastTokenOfTest.loc.end
74                             },
75                             messageId: "unexpectedTestCons",
76                             fix: fixer => {
77                                 if (hasComments) {
78                                     return null;
79                                 }
80                                 const fixers = [];
81                                 const areTestAndQuestionOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, questionToken);
82                                 const areQuestionAndConsOnSameLine = astUtils.isTokenOnSameLine(questionToken, firstTokenOfConsequent);
83
84                                 if (!areTestAndQuestionOnSameLine) {
85                                     fixers.push(fixer.removeRange([lastTokenOfTest.range[1], questionToken.range[0]]));
86                                 }
87                                 if (!areQuestionAndConsOnSameLine) {
88                                     fixers.push(fixer.removeRange([questionToken.range[1], firstTokenOfConsequent.range[0]]));
89                                 }
90
91                                 return fixers;
92                             }
93                         });
94                     }
95
96                     if (!areConsequentAndAlternateOnSameLine) {
97                         context.report({
98                             node: node.consequent,
99                             loc: {
100                                 start: firstTokenOfConsequent.loc.start,
101                                 end: lastTokenOfConsequent.loc.end
102                             },
103                             messageId: "unexpectedConsAlt",
104                             fix: fixer => {
105                                 if (hasComments) {
106                                     return null;
107                                 }
108                                 const fixers = [];
109                                 const areConsAndColonOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, colonToken);
110                                 const areColonAndAltOnSameLine = astUtils.isTokenOnSameLine(colonToken, firstTokenOfAlternate);
111
112                                 if (!areConsAndColonOnSameLine) {
113                                     fixers.push(fixer.removeRange([lastTokenOfConsequent.range[1], colonToken.range[0]]));
114                                 }
115                                 if (!areColonAndAltOnSameLine) {
116                                     fixers.push(fixer.removeRange([colonToken.range[1], firstTokenOfAlternate.range[0]]));
117                                 }
118
119                                 return fixers;
120                             }
121                         });
122                     }
123                 } else {
124                     if (allowSingleLine && node.loc.start.line === node.loc.end.line) {
125                         return;
126                     }
127
128                     if (areTestAndConsequentOnSameLine) {
129                         context.report({
130                             node: node.test,
131                             loc: {
132                                 start: firstTokenOfTest.loc.start,
133                                 end: lastTokenOfTest.loc.end
134                             },
135                             messageId: "expectedTestCons",
136                             fix: fixer => (hasComments ? null : (
137                                 fixer.replaceTextRange(
138                                     [
139                                         lastTokenOfTest.range[1],
140                                         questionToken.range[0]
141                                     ],
142                                     "\n"
143                                 )
144                             ))
145                         });
146                     }
147
148                     if (areConsequentAndAlternateOnSameLine) {
149                         context.report({
150                             node: node.consequent,
151                             loc: {
152                                 start: firstTokenOfConsequent.loc.start,
153                                 end: lastTokenOfConsequent.loc.end
154                             },
155                             messageId: "expectedConsAlt",
156                             fix: (fixer => (hasComments ? null : (
157                                 fixer.replaceTextRange(
158                                     [
159                                         lastTokenOfConsequent.range[1],
160                                         colonToken.range[0]
161                                     ],
162                                     "\n"
163                                 )
164                             )))
165                         });
166                     }
167                 }
168             }
169         };
170     }
171 };