]>
git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/space-unary-ops.js
04487c49e0d8c62bba7f80a765a10c9ca3057cf2
2 * @fileoverview This rule should require or disallow spaces before or after unary operations.
3 * @author Marcin Kumorek
7 //------------------------------------------------------------------------------
9 //------------------------------------------------------------------------------
11 const astUtils
= require("./utils/ast-utils");
13 //------------------------------------------------------------------------------
15 //------------------------------------------------------------------------------
17 /** @type {import('../shared/types').Rule} */
23 description
: "enforce consistent spacing before or after unary operators",
25 url
: "https://eslint.org/docs/rules/space-unary-ops"
28 fixable
: "whitespace",
44 additionalProperties
: {
49 additionalProperties
: false
53 unexpectedBefore
: "Unexpected space before unary operator '{{operator}}'.",
54 unexpectedAfter
: "Unexpected space after unary operator '{{operator}}'.",
55 unexpectedAfterWord
: "Unexpected space after unary word operator '{{word}}'.",
56 wordOperator
: "Unary word operator '{{word}}' must be followed by whitespace.",
57 operator
: "Unary operator '{{operator}}' must be followed by whitespace.",
58 beforeUnaryExpressions
: "Space is required before unary expressions '{{token}}'."
63 const options
= context
.options
[0] || { words
: true, nonwords
: false };
65 const sourceCode
= context
.getSourceCode();
67 //--------------------------------------------------------------------------
69 //--------------------------------------------------------------------------
72 * Check if the node is the first "!" in a "!!" convert to Boolean expression
73 * @param {ASTnode} node AST node
74 * @returns {boolean} Whether or not the node is first "!" in "!!"
76 function isFirstBangInBangBangExpression(node
) {
77 return node
&& node
.type
=== "UnaryExpression" && node
.argument
.operator
=== "!" &&
78 node
.argument
&& node
.argument
.type
=== "UnaryExpression" && node
.argument
.operator
=== "!";
82 * Checks if an override exists for a given operator.
83 * @param {string} operator Operator
84 * @returns {boolean} Whether or not an override has been provided for the operator
86 function overrideExistsForOperator(operator
) {
87 return options
.overrides
&& Object
.prototype.hasOwnProperty
.call(options
.overrides
, operator
);
91 * Gets the value that the override was set to for this operator
92 * @param {string} operator Operator
93 * @returns {boolean} Whether or not an override enforces a space with this operator
95 function overrideEnforcesSpaces(operator
) {
96 return options
.overrides
[operator
];
100 * Verify Unary Word Operator has spaces after the word operator
101 * @param {ASTnode} node AST node
102 * @param {Object} firstToken first token from the AST node
103 * @param {Object} secondToken second token from the AST node
104 * @param {string} word The word to be used for reporting
107 function verifyWordHasSpaces(node
, firstToken
, secondToken
, word
) {
108 if (secondToken
.range
[0] === firstToken
.range
[1]) {
111 messageId
: "wordOperator",
116 return fixer
.insertTextAfter(firstToken
, " ");
123 * Verify Unary Word Operator doesn't have spaces after the word operator
124 * @param {ASTnode} node AST node
125 * @param {Object} firstToken first token from the AST node
126 * @param {Object} secondToken second token from the AST node
127 * @param {string} word The word to be used for reporting
130 function verifyWordDoesntHaveSpaces(node
, firstToken
, secondToken
, word
) {
131 if (astUtils
.canTokensBeAdjacent(firstToken
, secondToken
)) {
132 if (secondToken
.range
[0] > firstToken
.range
[1]) {
135 messageId
: "unexpectedAfterWord",
140 return fixer
.removeRange([firstToken
.range
[1], secondToken
.range
[0]]);
148 * Check Unary Word Operators for spaces after the word operator
149 * @param {ASTnode} node AST node
150 * @param {Object} firstToken first token from the AST node
151 * @param {Object} secondToken second token from the AST node
152 * @param {string} word The word to be used for reporting
155 function checkUnaryWordOperatorForSpaces(node
, firstToken
, secondToken
, word
) {
156 if (overrideExistsForOperator(word
)) {
157 if (overrideEnforcesSpaces(word
)) {
158 verifyWordHasSpaces(node
, firstToken
, secondToken
, word
);
160 verifyWordDoesntHaveSpaces(node
, firstToken
, secondToken
, word
);
162 } else if (options
.words
) {
163 verifyWordHasSpaces(node
, firstToken
, secondToken
, word
);
165 verifyWordDoesntHaveSpaces(node
, firstToken
, secondToken
, word
);
170 * Verifies YieldExpressions satisfy spacing requirements
171 * @param {ASTnode} node AST node
174 function checkForSpacesAfterYield(node
) {
175 const tokens
= sourceCode
.getFirstTokens(node
, 3),
178 if (!node
.argument
|| node
.delegate
) {
182 checkUnaryWordOperatorForSpaces(node
, tokens
[0], tokens
[1], word
);
186 * Verifies AwaitExpressions satisfy spacing requirements
187 * @param {ASTNode} node AwaitExpression AST node
190 function checkForSpacesAfterAwait(node
) {
191 const tokens
= sourceCode
.getFirstTokens(node
, 3);
193 checkUnaryWordOperatorForSpaces(node
, tokens
[0], tokens
[1], "await");
197 * Verifies UnaryExpression, UpdateExpression and NewExpression have spaces before or after the operator
198 * @param {ASTnode} node AST node
199 * @param {Object} firstToken First token in the expression
200 * @param {Object} secondToken Second token in the expression
203 function verifyNonWordsHaveSpaces(node
, firstToken
, secondToken
) {
205 if (isFirstBangInBangBangExpression(node
)) {
208 if (firstToken
.range
[1] === secondToken
.range
[0]) {
211 messageId
: "operator",
213 operator
: firstToken
.value
216 return fixer
.insertTextAfter(firstToken
, " ");
221 if (firstToken
.range
[1] === secondToken
.range
[0]) {
224 messageId
: "beforeUnaryExpressions",
226 token
: secondToken
.value
229 return fixer
.insertTextBefore(secondToken
, " ");
237 * Verifies UnaryExpression, UpdateExpression and NewExpression don't have spaces before or after the operator
238 * @param {ASTnode} node AST node
239 * @param {Object} firstToken First token in the expression
240 * @param {Object} secondToken Second token in the expression
243 function verifyNonWordsDontHaveSpaces(node
, firstToken
, secondToken
) {
245 if (secondToken
.range
[0] > firstToken
.range
[1]) {
248 messageId
: "unexpectedAfter",
250 operator
: firstToken
.value
253 if (astUtils
.canTokensBeAdjacent(firstToken
, secondToken
)) {
254 return fixer
.removeRange([firstToken
.range
[1], secondToken
.range
[0]]);
261 if (secondToken
.range
[0] > firstToken
.range
[1]) {
264 messageId
: "unexpectedBefore",
266 operator
: secondToken
.value
269 return fixer
.removeRange([firstToken
.range
[1], secondToken
.range
[0]]);
277 * Verifies UnaryExpression, UpdateExpression and NewExpression satisfy spacing requirements
278 * @param {ASTnode} node AST node
281 function checkForSpaces(node
) {
282 const tokens
= node
.type
=== "UpdateExpression" && !node
.prefix
283 ? sourceCode
.getLastTokens(node
, 2)
284 : sourceCode
.getFirstTokens(node
, 2);
285 const firstToken
= tokens
[0];
286 const secondToken
= tokens
[1];
288 if ((node
.type
=== "NewExpression" || node
.prefix
) && firstToken
.type
=== "Keyword") {
289 checkUnaryWordOperatorForSpaces(node
, firstToken
, secondToken
, firstToken
.value
);
293 const operator
= node
.prefix
? tokens
[0].value
: tokens
[1].value
;
295 if (overrideExistsForOperator(operator
)) {
296 if (overrideEnforcesSpaces(operator
)) {
297 verifyNonWordsHaveSpaces(node
, firstToken
, secondToken
);
299 verifyNonWordsDontHaveSpaces(node
, firstToken
, secondToken
);
301 } else if (options
.nonwords
) {
302 verifyNonWordsHaveSpaces(node
, firstToken
, secondToken
);
304 verifyNonWordsDontHaveSpaces(node
, firstToken
, secondToken
);
308 //--------------------------------------------------------------------------
310 //--------------------------------------------------------------------------
313 UnaryExpression
: checkForSpaces
,
314 UpdateExpression
: checkForSpaces
,
315 NewExpression
: checkForSpaces
,
316 YieldExpression
: checkForSpacesAfterYield
,
317 AwaitExpression
: checkForSpacesAfterAwait