]>
git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/space-unary-ops.js
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 //------------------------------------------------------------------------------
22 description
: "enforce consistent spacing before or after unary operators",
24 url
: "https://eslint.org/docs/rules/space-unary-ops"
27 fixable
: "whitespace",
43 additionalProperties
: {
48 additionalProperties
: false
52 unexpectedBefore
: "Unexpected space before unary operator '{{operator}}'.",
53 unexpectedAfter
: "Unexpected space after unary operator '{{operator}}'.",
54 unexpectedAfterWord
: "Unexpected space after unary word operator '{{word}}'.",
55 wordOperator
: "Unary word operator '{{word}}' must be followed by whitespace.",
56 operator
: "Unary operator '{{operator}}' must be followed by whitespace.",
57 beforeUnaryExpressions
: "Space is required before unary expressions '{{token}}'."
62 const options
= context
.options
[0] || { words
: true, nonwords
: false };
64 const sourceCode
= context
.getSourceCode();
66 //--------------------------------------------------------------------------
68 //--------------------------------------------------------------------------
71 * Check if the node is the first "!" in a "!!" convert to Boolean expression
72 * @param {ASTnode} node AST node
73 * @returns {boolean} Whether or not the node is first "!" in "!!"
75 function isFirstBangInBangBangExpression(node
) {
76 return node
&& node
.type
=== "UnaryExpression" && node
.argument
.operator
=== "!" &&
77 node
.argument
&& node
.argument
.type
=== "UnaryExpression" && node
.argument
.operator
=== "!";
81 * Checks if an override exists for a given operator.
82 * @param {string} operator Operator
83 * @returns {boolean} Whether or not an override has been provided for the operator
85 function overrideExistsForOperator(operator
) {
86 return options
.overrides
&& Object
.prototype.hasOwnProperty
.call(options
.overrides
, operator
);
90 * Gets the value that the override was set to for this operator
91 * @param {string} operator Operator
92 * @returns {boolean} Whether or not an override enforces a space with this operator
94 function overrideEnforcesSpaces(operator
) {
95 return options
.overrides
[operator
];
99 * Verify Unary Word Operator has spaces after the word operator
100 * @param {ASTnode} node AST node
101 * @param {Object} firstToken first token from the AST node
102 * @param {Object} secondToken second token from the AST node
103 * @param {string} word The word to be used for reporting
106 function verifyWordHasSpaces(node
, firstToken
, secondToken
, word
) {
107 if (secondToken
.range
[0] === firstToken
.range
[1]) {
110 messageId
: "wordOperator",
115 return fixer
.insertTextAfter(firstToken
, " ");
122 * Verify Unary Word Operator doesn't have spaces after the word operator
123 * @param {ASTnode} node AST node
124 * @param {Object} firstToken first token from the AST node
125 * @param {Object} secondToken second token from the AST node
126 * @param {string} word The word to be used for reporting
129 function verifyWordDoesntHaveSpaces(node
, firstToken
, secondToken
, word
) {
130 if (astUtils
.canTokensBeAdjacent(firstToken
, secondToken
)) {
131 if (secondToken
.range
[0] > firstToken
.range
[1]) {
134 messageId
: "unexpectedAfterWord",
139 return fixer
.removeRange([firstToken
.range
[1], secondToken
.range
[0]]);
147 * Check Unary Word Operators for spaces after the word operator
148 * @param {ASTnode} node AST node
149 * @param {Object} firstToken first token from the AST node
150 * @param {Object} secondToken second token from the AST node
151 * @param {string} word The word to be used for reporting
154 function checkUnaryWordOperatorForSpaces(node
, firstToken
, secondToken
, word
) {
155 if (overrideExistsForOperator(word
)) {
156 if (overrideEnforcesSpaces(word
)) {
157 verifyWordHasSpaces(node
, firstToken
, secondToken
, word
);
159 verifyWordDoesntHaveSpaces(node
, firstToken
, secondToken
, word
);
161 } else if (options
.words
) {
162 verifyWordHasSpaces(node
, firstToken
, secondToken
, word
);
164 verifyWordDoesntHaveSpaces(node
, firstToken
, secondToken
, word
);
169 * Verifies YieldExpressions satisfy spacing requirements
170 * @param {ASTnode} node AST node
173 function checkForSpacesAfterYield(node
) {
174 const tokens
= sourceCode
.getFirstTokens(node
, 3),
177 if (!node
.argument
|| node
.delegate
) {
181 checkUnaryWordOperatorForSpaces(node
, tokens
[0], tokens
[1], word
);
185 * Verifies AwaitExpressions satisfy spacing requirements
186 * @param {ASTNode} node AwaitExpression AST node
189 function checkForSpacesAfterAwait(node
) {
190 const tokens
= sourceCode
.getFirstTokens(node
, 3);
192 checkUnaryWordOperatorForSpaces(node
, tokens
[0], tokens
[1], "await");
196 * Verifies UnaryExpression, UpdateExpression and NewExpression have spaces before or after the operator
197 * @param {ASTnode} node AST node
198 * @param {Object} firstToken First token in the expression
199 * @param {Object} secondToken Second token in the expression
202 function verifyNonWordsHaveSpaces(node
, firstToken
, secondToken
) {
204 if (isFirstBangInBangBangExpression(node
)) {
207 if (firstToken
.range
[1] === secondToken
.range
[0]) {
210 messageId
: "operator",
212 operator
: firstToken
.value
215 return fixer
.insertTextAfter(firstToken
, " ");
220 if (firstToken
.range
[1] === secondToken
.range
[0]) {
223 messageId
: "beforeUnaryExpressions",
225 token
: secondToken
.value
228 return fixer
.insertTextBefore(secondToken
, " ");
236 * Verifies UnaryExpression, UpdateExpression and NewExpression don't have spaces before or after the operator
237 * @param {ASTnode} node AST node
238 * @param {Object} firstToken First token in the expression
239 * @param {Object} secondToken Second token in the expression
242 function verifyNonWordsDontHaveSpaces(node
, firstToken
, secondToken
) {
244 if (secondToken
.range
[0] > firstToken
.range
[1]) {
247 messageId
: "unexpectedAfter",
249 operator
: firstToken
.value
252 if (astUtils
.canTokensBeAdjacent(firstToken
, secondToken
)) {
253 return fixer
.removeRange([firstToken
.range
[1], secondToken
.range
[0]]);
260 if (secondToken
.range
[0] > firstToken
.range
[1]) {
263 messageId
: "unexpectedBefore",
265 operator
: secondToken
.value
268 return fixer
.removeRange([firstToken
.range
[1], secondToken
.range
[0]]);
276 * Verifies UnaryExpression, UpdateExpression and NewExpression satisfy spacing requirements
277 * @param {ASTnode} node AST node
280 function checkForSpaces(node
) {
281 const tokens
= node
.type
=== "UpdateExpression" && !node
.prefix
282 ? sourceCode
.getLastTokens(node
, 2)
283 : sourceCode
.getFirstTokens(node
, 2);
284 const firstToken
= tokens
[0];
285 const secondToken
= tokens
[1];
287 if ((node
.type
=== "NewExpression" || node
.prefix
) && firstToken
.type
=== "Keyword") {
288 checkUnaryWordOperatorForSpaces(node
, firstToken
, secondToken
, firstToken
.value
);
292 const operator
= node
.prefix
? tokens
[0].value
: tokens
[1].value
;
294 if (overrideExistsForOperator(operator
)) {
295 if (overrideEnforcesSpaces(operator
)) {
296 verifyNonWordsHaveSpaces(node
, firstToken
, secondToken
);
298 verifyNonWordsDontHaveSpaces(node
, firstToken
, secondToken
);
300 } else if (options
.nonwords
) {
301 verifyNonWordsHaveSpaces(node
, firstToken
, secondToken
);
303 verifyNonWordsDontHaveSpaces(node
, firstToken
, secondToken
);
307 //--------------------------------------------------------------------------
309 //--------------------------------------------------------------------------
312 UnaryExpression
: checkForSpaces
,
313 UpdateExpression
: checkForSpaces
,
314 NewExpression
: checkForSpaces
,
315 YieldExpression
: checkForSpacesAfterYield
,
316 AwaitExpression
: checkForSpacesAfterAwait