]> git.proxmox.com Git - pve-eslint.git/blame - eslint/lib/rules/block-spacing.js
import 8.4.0 source
[pve-eslint.git] / eslint / lib / rules / block-spacing.js
CommitLineData
eb39fafa
DC
1/**
2 * @fileoverview A rule to disallow or enforce spaces inside of single line blocks.
3 * @author Toru Nagashima
4 */
5
6"use strict";
7
8const util = require("./utils/ast-utils");
9
10//------------------------------------------------------------------------------
11// Rule Definition
12//------------------------------------------------------------------------------
13
34eeec05 14/** @type {import('../shared/types').Rule} */
eb39fafa
DC
15module.exports = {
16 meta: {
17 type: "layout",
18
19 docs: {
20 description: "disallow or enforce spaces inside of blocks after opening block and before closing block",
eb39fafa
DC
21 recommended: false,
22 url: "https://eslint.org/docs/rules/block-spacing"
23 },
24
25 fixable: "whitespace",
26
27 schema: [
28 { enum: ["always", "never"] }
29 ],
30
31 messages: {
32 missing: "Requires a space {{location}} '{{token}}'.",
33 extra: "Unexpected space(s) {{location}} '{{token}}'."
34 }
35 },
36
37 create(context) {
38 const always = (context.options[0] !== "never"),
39 messageId = always ? "missing" : "extra",
40 sourceCode = context.getSourceCode();
41
42 /**
43 * Gets the open brace token from a given node.
609c276f 44 * @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to get.
eb39fafa
DC
45 * @returns {Token} The token of the open brace.
46 */
47 function getOpenBrace(node) {
48 if (node.type === "SwitchStatement") {
49 if (node.cases.length > 0) {
50 return sourceCode.getTokenBefore(node.cases[0]);
51 }
52 return sourceCode.getLastToken(node, 1);
53 }
609c276f
TL
54
55 if (node.type === "StaticBlock") {
56 return sourceCode.getFirstToken(node, { skip: 1 }); // skip the `static` token
57 }
58
59 // "BlockStatement"
eb39fafa
DC
60 return sourceCode.getFirstToken(node);
61 }
62
63 /**
64 * Checks whether or not:
65 * - given tokens are on same line.
66 * - there is/isn't a space between given tokens.
67 * @param {Token} left A token to check.
68 * @param {Token} right The token which is next to `left`.
69 * @returns {boolean}
70 * When the option is `"always"`, `true` if there are one or more spaces between given tokens.
71 * When the option is `"never"`, `true` if there are not any spaces between given tokens.
72 * If given tokens are not on same line, it's always `true`.
73 */
74 function isValid(left, right) {
75 return (
76 !util.isTokenOnSameLine(left, right) ||
77 sourceCode.isSpaceBetweenTokens(left, right) === always
78 );
79 }
80
81 /**
609c276f
TL
82 * Checks and reports invalid spacing style inside braces.
83 * @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to check.
eb39fafa
DC
84 * @returns {void}
85 */
86 function checkSpacingInsideBraces(node) {
87
88 // Gets braces and the first/last token of content.
89 const openBrace = getOpenBrace(node);
90 const closeBrace = sourceCode.getLastToken(node);
91 const firstToken = sourceCode.getTokenAfter(openBrace, { includeComments: true });
92 const lastToken = sourceCode.getTokenBefore(closeBrace, { includeComments: true });
93
94 // Skip if the node is invalid or empty.
95 if (openBrace.type !== "Punctuator" ||
96 openBrace.value !== "{" ||
97 closeBrace.type !== "Punctuator" ||
98 closeBrace.value !== "}" ||
99 firstToken === closeBrace
100 ) {
101 return;
102 }
103
104 // Skip line comments for option never
105 if (!always && firstToken.type === "Line") {
106 return;
107 }
108
109 // Check.
110 if (!isValid(openBrace, firstToken)) {
ebb53d86
TL
111 let loc = openBrace.loc;
112
113 if (messageId === "extra") {
114 loc = {
115 start: openBrace.loc.end,
116 end: firstToken.loc.start
117 };
118 }
119
eb39fafa
DC
120 context.report({
121 node,
ebb53d86 122 loc,
eb39fafa
DC
123 messageId,
124 data: {
125 location: "after",
126 token: openBrace.value
127 },
128 fix(fixer) {
129 if (always) {
130 return fixer.insertTextBefore(firstToken, " ");
131 }
132
133 return fixer.removeRange([openBrace.range[1], firstToken.range[0]]);
134 }
135 });
136 }
137 if (!isValid(lastToken, closeBrace)) {
ebb53d86
TL
138 let loc = closeBrace.loc;
139
140 if (messageId === "extra") {
141 loc = {
142 start: lastToken.loc.end,
143 end: closeBrace.loc.start
144 };
145 }
eb39fafa
DC
146 context.report({
147 node,
ebb53d86 148 loc,
eb39fafa
DC
149 messageId,
150 data: {
151 location: "before",
152 token: closeBrace.value
153 },
154 fix(fixer) {
155 if (always) {
156 return fixer.insertTextAfter(lastToken, " ");
157 }
158
159 return fixer.removeRange([lastToken.range[1], closeBrace.range[0]]);
160 }
161 });
162 }
163 }
164
165 return {
166 BlockStatement: checkSpacingInsideBraces,
609c276f 167 StaticBlock: checkSpacingInsideBraces,
eb39fafa
DC
168 SwitchStatement: checkSpacingInsideBraces
169 };
170 }
171};