]>
git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/padded-blocks.js
2 * @fileoverview A rule to ensure blank lines within blocks.
3 * @author Mathias Schreck <https://github.com/lo1tuma>
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
12 const astUtils
= require("./utils/ast-utils");
14 //------------------------------------------------------------------------------
16 //------------------------------------------------------------------------------
23 description
: "require or disallow padding within blocks",
24 category
: "Stylistic Issues",
26 url
: "https://eslint.org/docs/rules/padded-blocks"
29 fixable
: "whitespace",
35 enum: ["always", "never"]
41 enum: ["always", "never"]
44 enum: ["always", "never"]
47 enum: ["always", "never"]
50 additionalProperties
: false,
58 allowSingleLineBlocks
: {
66 alwaysPadBlock
: "Block must be padded by blank lines.",
67 neverPadBlock
: "Block must not be padded by blank lines."
73 const typeOptions
= context
.options
[0] || "always";
74 const exceptOptions
= context
.options
[1] || {};
76 if (typeof typeOptions
=== "string") {
77 const shouldHavePadding
= typeOptions
=== "always";
79 options
.blocks
= shouldHavePadding
;
80 options
.switches
= shouldHavePadding
;
81 options
.classes
= shouldHavePadding
;
83 if (Object
.prototype.hasOwnProperty
.call(typeOptions
, "blocks")) {
84 options
.blocks
= typeOptions
.blocks
=== "always";
86 if (Object
.prototype.hasOwnProperty
.call(typeOptions
, "switches")) {
87 options
.switches
= typeOptions
.switches
=== "always";
89 if (Object
.prototype.hasOwnProperty
.call(typeOptions
, "classes")) {
90 options
.classes
= typeOptions
.classes
=== "always";
94 if (Object
.prototype.hasOwnProperty
.call(exceptOptions
, "allowSingleLineBlocks")) {
95 options
.allowSingleLineBlocks
= exceptOptions
.allowSingleLineBlocks
=== true;
98 const sourceCode
= context
.getSourceCode();
101 * Gets the open brace token from a given node.
102 * @param {ASTNode} node A BlockStatement or SwitchStatement node from which to get the open brace.
103 * @returns {Token} The token of the open brace.
105 function getOpenBrace(node
) {
106 if (node
.type
=== "SwitchStatement") {
107 return sourceCode
.getTokenBefore(node
.cases
[0]);
109 return sourceCode
.getFirstToken(node
);
113 * Checks if the given parameter is a comment node
114 * @param {ASTNode|Token} node An AST node or token
115 * @returns {boolean} True if node is a comment
117 function isComment(node
) {
118 return node
.type
=== "Line" || node
.type
=== "Block";
122 * Checks if there is padding between two tokens
123 * @param {Token} first The first token
124 * @param {Token} second The second token
125 * @returns {boolean} True if there is at least a line between the tokens
127 function isPaddingBetweenTokens(first
, second
) {
128 return second
.loc
.start
.line
- first
.loc
.end
.line
>= 2;
133 * Checks if the given token has a blank line after it.
134 * @param {Token} token The token to check.
135 * @returns {boolean} Whether or not the token is followed by a blank line.
137 function getFirstBlockToken(token
) {
143 first
= sourceCode
.getTokenAfter(first
, { includeComments
: true });
144 } while (isComment(first
) && first
.loc
.start
.line
=== prev
.loc
.end
.line
);
150 * Checks if the given token is preceded by a blank line.
151 * @param {Token} token The token to check
152 * @returns {boolean} Whether or not the token is preceded by a blank line
154 function getLastBlockToken(token
) {
160 last
= sourceCode
.getTokenBefore(last
, { includeComments
: true });
161 } while (isComment(last
) && last
.loc
.end
.line
=== next
.loc
.start
.line
);
167 * Checks if a node should be padded, according to the rule config.
168 * @param {ASTNode} node The AST node to check.
169 * @returns {boolean} True if the node should be padded, false otherwise.
171 function requirePaddingFor(node
) {
173 case "BlockStatement":
174 return options
.blocks
;
175 case "SwitchStatement":
176 return options
.switches
;
178 return options
.classes
;
180 /* istanbul ignore next */
182 throw new Error("unreachable");
187 * Checks the given BlockStatement node to be padded if the block is not empty.
188 * @param {ASTNode} node The AST node of a BlockStatement.
189 * @returns {void} undefined.
191 function checkPadding(node
) {
192 const openBrace
= getOpenBrace(node
),
193 firstBlockToken
= getFirstBlockToken(openBrace
),
194 tokenBeforeFirst
= sourceCode
.getTokenBefore(firstBlockToken
, { includeComments
: true }),
195 closeBrace
= sourceCode
.getLastToken(node
),
196 lastBlockToken
= getLastBlockToken(closeBrace
),
197 tokenAfterLast
= sourceCode
.getTokenAfter(lastBlockToken
, { includeComments
: true }),
198 blockHasTopPadding
= isPaddingBetweenTokens(tokenBeforeFirst
, firstBlockToken
),
199 blockHasBottomPadding
= isPaddingBetweenTokens(lastBlockToken
, tokenAfterLast
);
201 if (options
.allowSingleLineBlocks
&& astUtils
.isTokenOnSameLine(tokenBeforeFirst
, tokenAfterLast
)) {
205 if (requirePaddingFor(node
)) {
206 if (!blockHasTopPadding
) {
209 loc
: { line
: tokenBeforeFirst
.loc
.start
.line
, column
: tokenBeforeFirst
.loc
.start
.column
},
211 return fixer
.insertTextAfter(tokenBeforeFirst
, "\n");
213 messageId
: "alwaysPadBlock"
216 if (!blockHasBottomPadding
) {
219 loc
: { line
: tokenAfterLast
.loc
.end
.line
, column
: tokenAfterLast
.loc
.end
.column
- 1 },
221 return fixer
.insertTextBefore(tokenAfterLast
, "\n");
223 messageId
: "alwaysPadBlock"
227 if (blockHasTopPadding
) {
231 loc
: { line
: tokenBeforeFirst
.loc
.start
.line
, column
: tokenBeforeFirst
.loc
.start
.column
},
233 return fixer
.replaceTextRange([tokenBeforeFirst
.range
[1], firstBlockToken
.range
[0] - firstBlockToken
.loc
.start
.column
], "\n");
235 messageId
: "neverPadBlock"
239 if (blockHasBottomPadding
) {
243 loc
: { line
: tokenAfterLast
.loc
.end
.line
, column
: tokenAfterLast
.loc
.end
.column
- 1 },
244 messageId
: "neverPadBlock",
246 return fixer
.replaceTextRange([lastBlockToken
.range
[1], tokenAfterLast
.range
[0] - tokenAfterLast
.loc
.start
.column
], "\n");
255 if (Object
.prototype.hasOwnProperty
.call(options
, "switches")) {
256 rule
.SwitchStatement = function(node
) {
257 if (node
.cases
.length
=== 0) {
264 if (Object
.prototype.hasOwnProperty
.call(options
, "blocks")) {
265 rule
.BlockStatement = function(node
) {
266 if (node
.body
.length
=== 0) {
273 if (Object
.prototype.hasOwnProperty
.call(options
, "classes")) {
274 rule
.ClassBody = function(node
) {
275 if (node
.body
.length
=== 0) {