source: imaps-frontend/node_modules/eslint/lib/rules/operator-linebreak.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 9.9 KB
Line 
1/**
2 * @fileoverview Operator linebreak - enforces operator linebreak style of two types: after and before
3 * @author Benoît Zugmeyer
4 * @deprecated in ESLint v8.53.0
5 */
6
7"use strict";
8
9//------------------------------------------------------------------------------
10// Requirements
11//------------------------------------------------------------------------------
12
13const astUtils = require("./utils/ast-utils");
14
15//------------------------------------------------------------------------------
16// Rule Definition
17//------------------------------------------------------------------------------
18
19/** @type {import('../shared/types').Rule} */
20module.exports = {
21 meta: {
22 deprecated: true,
23 replacedBy: [],
24 type: "layout",
25
26 docs: {
27 description: "Enforce consistent linebreak style for operators",
28 recommended: false,
29 url: "https://eslint.org/docs/latest/rules/operator-linebreak"
30 },
31
32 schema: [
33 {
34 enum: ["after", "before", "none", null]
35 },
36 {
37 type: "object",
38 properties: {
39 overrides: {
40 type: "object",
41 additionalProperties: {
42 enum: ["after", "before", "none", "ignore"]
43 }
44 }
45 },
46 additionalProperties: false
47 }
48 ],
49
50 fixable: "code",
51
52 messages: {
53 operatorAtBeginning: "'{{operator}}' should be placed at the beginning of the line.",
54 operatorAtEnd: "'{{operator}}' should be placed at the end of the line.",
55 badLinebreak: "Bad line breaking before and after '{{operator}}'.",
56 noLinebreak: "There should be no line break before or after '{{operator}}'."
57 }
58 },
59
60 create(context) {
61
62 const usedDefaultGlobal = !context.options[0];
63 const globalStyle = context.options[0] || "after";
64 const options = context.options[1] || {};
65 const styleOverrides = options.overrides ? Object.assign({}, options.overrides) : {};
66
67 if (usedDefaultGlobal && !styleOverrides["?"]) {
68 styleOverrides["?"] = "before";
69 }
70
71 if (usedDefaultGlobal && !styleOverrides[":"]) {
72 styleOverrides[":"] = "before";
73 }
74
75 const sourceCode = context.sourceCode;
76
77 //--------------------------------------------------------------------------
78 // Helpers
79 //--------------------------------------------------------------------------
80
81 /**
82 * Gets a fixer function to fix rule issues
83 * @param {Token} operatorToken The operator token of an expression
84 * @param {string} desiredStyle The style for the rule. One of 'before', 'after', 'none'
85 * @returns {Function} A fixer function
86 */
87 function getFixer(operatorToken, desiredStyle) {
88 return fixer => {
89 const tokenBefore = sourceCode.getTokenBefore(operatorToken);
90 const tokenAfter = sourceCode.getTokenAfter(operatorToken);
91 const textBefore = sourceCode.text.slice(tokenBefore.range[1], operatorToken.range[0]);
92 const textAfter = sourceCode.text.slice(operatorToken.range[1], tokenAfter.range[0]);
93 const hasLinebreakBefore = !astUtils.isTokenOnSameLine(tokenBefore, operatorToken);
94 const hasLinebreakAfter = !astUtils.isTokenOnSameLine(operatorToken, tokenAfter);
95 let newTextBefore, newTextAfter;
96
97 if (hasLinebreakBefore !== hasLinebreakAfter && desiredStyle !== "none") {
98
99 // If there is a comment before and after the operator, don't do a fix.
100 if (sourceCode.getTokenBefore(operatorToken, { includeComments: true }) !== tokenBefore &&
101 sourceCode.getTokenAfter(operatorToken, { includeComments: true }) !== tokenAfter) {
102
103 return null;
104 }
105
106 /*
107 * If there is only one linebreak and it's on the wrong side of the operator, swap the text before and after the operator.
108 * foo &&
109 * bar
110 * would get fixed to
111 * foo
112 * && bar
113 */
114 newTextBefore = textAfter;
115 newTextAfter = textBefore;
116 } else {
117 const LINEBREAK_REGEX = astUtils.createGlobalLinebreakMatcher();
118
119 // Otherwise, if no linebreak is desired and no comments interfere, replace the linebreaks with empty strings.
120 newTextBefore = desiredStyle === "before" || textBefore.trim() ? textBefore : textBefore.replace(LINEBREAK_REGEX, "");
121 newTextAfter = desiredStyle === "after" || textAfter.trim() ? textAfter : textAfter.replace(LINEBREAK_REGEX, "");
122
123 // If there was no change (due to interfering comments), don't output a fix.
124 if (newTextBefore === textBefore && newTextAfter === textAfter) {
125 return null;
126 }
127 }
128
129 if (newTextAfter === "" && tokenAfter.type === "Punctuator" && "+-".includes(operatorToken.value) && tokenAfter.value === operatorToken.value) {
130
131 // To avoid accidentally creating a ++ or -- operator, insert a space if the operator is a +/- and the following token is a unary +/-.
132 newTextAfter += " ";
133 }
134
135 return fixer.replaceTextRange([tokenBefore.range[1], tokenAfter.range[0]], newTextBefore + operatorToken.value + newTextAfter);
136 };
137 }
138
139 /**
140 * Checks the operator placement
141 * @param {ASTNode} node The node to check
142 * @param {ASTNode} rightSide The node that comes after the operator in `node`
143 * @param {string} operator The operator
144 * @private
145 * @returns {void}
146 */
147 function validateNode(node, rightSide, operator) {
148
149 /*
150 * Find the operator token by searching from the right side, because between the left side and the operator
151 * there could be additional tokens from type annotations. Search specifically for the token which
152 * value equals the operator, in order to skip possible opening parentheses before the right side node.
153 */
154 const operatorToken = sourceCode.getTokenBefore(rightSide, token => token.value === operator);
155 const leftToken = sourceCode.getTokenBefore(operatorToken);
156 const rightToken = sourceCode.getTokenAfter(operatorToken);
157 const operatorStyleOverride = styleOverrides[operator];
158 const style = operatorStyleOverride || globalStyle;
159 const fix = getFixer(operatorToken, style);
160
161 // if single line
162 if (astUtils.isTokenOnSameLine(leftToken, operatorToken) &&
163 astUtils.isTokenOnSameLine(operatorToken, rightToken)) {
164
165 // do nothing.
166
167 } else if (operatorStyleOverride !== "ignore" && !astUtils.isTokenOnSameLine(leftToken, operatorToken) &&
168 !astUtils.isTokenOnSameLine(operatorToken, rightToken)) {
169
170 // lone operator
171 context.report({
172 node,
173 loc: operatorToken.loc,
174 messageId: "badLinebreak",
175 data: {
176 operator
177 },
178 fix
179 });
180
181 } else if (style === "before" && astUtils.isTokenOnSameLine(leftToken, operatorToken)) {
182
183 context.report({
184 node,
185 loc: operatorToken.loc,
186 messageId: "operatorAtBeginning",
187 data: {
188 operator
189 },
190 fix
191 });
192
193 } else if (style === "after" && astUtils.isTokenOnSameLine(operatorToken, rightToken)) {
194
195 context.report({
196 node,
197 loc: operatorToken.loc,
198 messageId: "operatorAtEnd",
199 data: {
200 operator
201 },
202 fix
203 });
204
205 } else if (style === "none") {
206
207 context.report({
208 node,
209 loc: operatorToken.loc,
210 messageId: "noLinebreak",
211 data: {
212 operator
213 },
214 fix
215 });
216
217 }
218 }
219
220 /**
221 * Validates a binary expression using `validateNode`
222 * @param {BinaryExpression|LogicalExpression|AssignmentExpression} node node to be validated
223 * @returns {void}
224 */
225 function validateBinaryExpression(node) {
226 validateNode(node, node.right, node.operator);
227 }
228
229 //--------------------------------------------------------------------------
230 // Public
231 //--------------------------------------------------------------------------
232
233 return {
234 BinaryExpression: validateBinaryExpression,
235 LogicalExpression: validateBinaryExpression,
236 AssignmentExpression: validateBinaryExpression,
237 VariableDeclarator(node) {
238 if (node.init) {
239 validateNode(node, node.init, "=");
240 }
241 },
242 PropertyDefinition(node) {
243 if (node.value) {
244 validateNode(node, node.value, "=");
245 }
246 },
247 ConditionalExpression(node) {
248 validateNode(node, node.consequent, "?");
249 validateNode(node, node.alternate, ":");
250 }
251 };
252 }
253};
Note: See TracBrowser for help on using the repository browser.