]>
git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/space-in-parens.js
2 * @fileoverview Disallows or enforces spaces inside of parentheses.
3 * @author Jonathan Rajavuori
7 const astUtils
= require("./utils/ast-utils");
9 //------------------------------------------------------------------------------
11 //------------------------------------------------------------------------------
13 /** @type {import('../shared/types').Rule} */
19 description
: "enforce consistent spacing inside parentheses",
21 url
: "https://eslint.org/docs/rules/space-in-parens"
24 fixable
: "whitespace",
28 enum: ["always", "never"]
36 enum: ["{}", "[]", "()", "empty"]
41 additionalProperties
: false
46 missingOpeningSpace
: "There must be a space after this paren.",
47 missingClosingSpace
: "There must be a space before this paren.",
48 rejectedOpeningSpace
: "There should be no space after this paren.",
49 rejectedClosingSpace
: "There should be no space before this paren."
54 const ALWAYS
= context
.options
[0] === "always",
55 exceptionsArrayOptions
= (context
.options
[1] && context
.options
[1].exceptions
) || [],
60 if (exceptionsArrayOptions
.length
) {
61 options
.braceException
= exceptionsArrayOptions
.includes("{}");
62 options
.bracketException
= exceptionsArrayOptions
.includes("[]");
63 options
.parenException
= exceptionsArrayOptions
.includes("()");
64 options
.empty
= exceptionsArrayOptions
.includes("empty");
68 * Produces an object with the opener and closer exception values
69 * @returns {Object} `openers` and `closers` exception values
72 function getExceptions() {
76 if (options
.braceException
) {
81 if (options
.bracketException
) {
86 if (options
.parenException
) {
102 //--------------------------------------------------------------------------
104 //--------------------------------------------------------------------------
105 const sourceCode
= context
.getSourceCode();
108 * Determines if a token is one of the exceptions for the opener paren
109 * @param {Object} token The token to check
110 * @returns {boolean} True if the token is one of the exceptions for the opener paren
112 function isOpenerException(token
) {
113 return exceptions
.openers
.includes(token
.value
);
117 * Determines if a token is one of the exceptions for the closer paren
118 * @param {Object} token The token to check
119 * @returns {boolean} True if the token is one of the exceptions for the closer paren
121 function isCloserException(token
) {
122 return exceptions
.closers
.includes(token
.value
);
126 * Determines if an opening paren is immediately followed by a required space
127 * @param {Object} openingParenToken The paren token
128 * @param {Object} tokenAfterOpeningParen The token after it
129 * @returns {boolean} True if the opening paren is missing a required space
131 function openerMissingSpace(openingParenToken
, tokenAfterOpeningParen
) {
132 if (sourceCode
.isSpaceBetweenTokens(openingParenToken
, tokenAfterOpeningParen
)) {
136 if (!options
.empty
&& astUtils
.isClosingParenToken(tokenAfterOpeningParen
)) {
141 return !isOpenerException(tokenAfterOpeningParen
);
143 return isOpenerException(tokenAfterOpeningParen
);
147 * Determines if an opening paren is immediately followed by a disallowed space
148 * @param {Object} openingParenToken The paren token
149 * @param {Object} tokenAfterOpeningParen The token after it
150 * @returns {boolean} True if the opening paren has a disallowed space
152 function openerRejectsSpace(openingParenToken
, tokenAfterOpeningParen
) {
153 if (!astUtils
.isTokenOnSameLine(openingParenToken
, tokenAfterOpeningParen
)) {
157 if (tokenAfterOpeningParen
.type
=== "Line") {
161 if (!sourceCode
.isSpaceBetweenTokens(openingParenToken
, tokenAfterOpeningParen
)) {
166 return isOpenerException(tokenAfterOpeningParen
);
168 return !isOpenerException(tokenAfterOpeningParen
);
172 * Determines if a closing paren is immediately preceded by a required space
173 * @param {Object} tokenBeforeClosingParen The token before the paren
174 * @param {Object} closingParenToken The paren token
175 * @returns {boolean} True if the closing paren is missing a required space
177 function closerMissingSpace(tokenBeforeClosingParen
, closingParenToken
) {
178 if (sourceCode
.isSpaceBetweenTokens(tokenBeforeClosingParen
, closingParenToken
)) {
182 if (!options
.empty
&& astUtils
.isOpeningParenToken(tokenBeforeClosingParen
)) {
187 return !isCloserException(tokenBeforeClosingParen
);
189 return isCloserException(tokenBeforeClosingParen
);
193 * Determines if a closer paren is immediately preceded by a disallowed space
194 * @param {Object} tokenBeforeClosingParen The token before the paren
195 * @param {Object} closingParenToken The paren token
196 * @returns {boolean} True if the closing paren has a disallowed space
198 function closerRejectsSpace(tokenBeforeClosingParen
, closingParenToken
) {
199 if (!astUtils
.isTokenOnSameLine(tokenBeforeClosingParen
, closingParenToken
)) {
203 if (!sourceCode
.isSpaceBetweenTokens(tokenBeforeClosingParen
, closingParenToken
)) {
208 return isCloserException(tokenBeforeClosingParen
);
210 return !isCloserException(tokenBeforeClosingParen
);
213 //--------------------------------------------------------------------------
215 //--------------------------------------------------------------------------
218 Program
: function checkParenSpaces(node
) {
219 exceptions
= getExceptions();
220 const tokens
= sourceCode
.tokensAndComments
;
222 tokens
.forEach((token
, i
) => {
223 const prevToken
= tokens
[i
- 1];
224 const nextToken
= tokens
[i
+ 1];
226 // if token is not an opening or closing paren token, do nothing
227 if (!astUtils
.isOpeningParenToken(token
) && !astUtils
.isClosingParenToken(token
)) {
231 // if token is an opening paren and is not followed by a required space
232 if (token
.value
=== "(" && openerMissingSpace(token
, nextToken
)) {
236 messageId
: "missingOpeningSpace",
238 return fixer
.insertTextAfter(token
, " ");
243 // if token is an opening paren and is followed by a disallowed space
244 if (token
.value
=== "(" && openerRejectsSpace(token
, nextToken
)) {
247 loc
: { start
: token
.loc
.end
, end
: nextToken
.loc
.start
},
248 messageId
: "rejectedOpeningSpace",
250 return fixer
.removeRange([token
.range
[1], nextToken
.range
[0]]);
255 // if token is a closing paren and is not preceded by a required space
256 if (token
.value
=== ")" && closerMissingSpace(prevToken
, token
)) {
260 messageId
: "missingClosingSpace",
262 return fixer
.insertTextBefore(token
, " ");
267 // if token is a closing paren and is preceded by a disallowed space
268 if (token
.value
=== ")" && closerRejectsSpace(prevToken
, token
)) {
271 loc
: { start
: prevToken
.loc
.end
, end
: token
.loc
.start
},
272 messageId
: "rejectedClosingSpace",
274 return fixer
.removeRange([prevToken
.range
[1], token
.range
[0]]);