UNPKG

9.8 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const utils_1 = require("@typescript-eslint/utils");
4const getESLintCoreRule_1 = require("../util/getESLintCoreRule");
5const util_1 = require("../util");
6const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('object-curly-spacing');
7exports.default = (0, util_1.createRule)({
8 name: 'object-curly-spacing',
9 meta: Object.assign(Object.assign({}, baseRule.meta), { docs: {
10 description: 'Enforce consistent spacing inside braces',
11 recommended: false,
12 extendsBaseRule: true,
13 } }),
14 defaultOptions: ['never'],
15 create(context) {
16 const [firstOption, secondOption] = context.options;
17 const spaced = firstOption === 'always';
18 const sourceCode = context.getSourceCode();
19 /**
20 * Determines whether an option is set, relative to the spacing option.
21 * If spaced is "always", then check whether option is set to false.
22 * If spaced is "never", then check whether option is set to true.
23 * @param option The option to exclude.
24 * @returns Whether or not the property is excluded.
25 */
26 function isOptionSet(option) {
27 return secondOption ? secondOption[option] === !spaced : false;
28 }
29 const options = {
30 spaced,
31 arraysInObjectsException: isOptionSet('arraysInObjects'),
32 objectsInObjectsException: isOptionSet('objectsInObjects'),
33 };
34 //--------------------------------------------------------------------------
35 // Helpers
36 //--------------------------------------------------------------------------
37 /**
38 * Reports that there shouldn't be a space after the first token
39 * @param node The node to report in the event of an error.
40 * @param token The token to use for the report.
41 */
42 function reportNoBeginningSpace(node, token) {
43 const nextToken = context
44 .getSourceCode()
45 .getTokenAfter(token, { includeComments: true });
46 context.report({
47 node,
48 loc: { start: token.loc.end, end: nextToken.loc.start },
49 messageId: 'unexpectedSpaceAfter',
50 data: {
51 token: token.value,
52 },
53 fix(fixer) {
54 return fixer.removeRange([token.range[1], nextToken.range[0]]);
55 },
56 });
57 }
58 /**
59 * Reports that there shouldn't be a space before the last token
60 * @param node The node to report in the event of an error.
61 * @param token The token to use for the report.
62 */
63 function reportNoEndingSpace(node, token) {
64 const previousToken = context
65 .getSourceCode()
66 .getTokenBefore(token, { includeComments: true });
67 context.report({
68 node,
69 loc: { start: previousToken.loc.end, end: token.loc.start },
70 messageId: 'unexpectedSpaceBefore',
71 data: {
72 token: token.value,
73 },
74 fix(fixer) {
75 return fixer.removeRange([previousToken.range[1], token.range[0]]);
76 },
77 });
78 }
79 /**
80 * Reports that there should be a space after the first token
81 * @param node The node to report in the event of an error.
82 * @param token The token to use for the report.
83 */
84 function reportRequiredBeginningSpace(node, token) {
85 context.report({
86 node,
87 loc: token.loc,
88 messageId: 'requireSpaceAfter',
89 data: {
90 token: token.value,
91 },
92 fix(fixer) {
93 return fixer.insertTextAfter(token, ' ');
94 },
95 });
96 }
97 /**
98 * Reports that there should be a space before the last token
99 * @param node The node to report in the event of an error.
100 * @param token The token to use for the report.
101 */
102 function reportRequiredEndingSpace(node, token) {
103 context.report({
104 node,
105 loc: token.loc,
106 messageId: 'requireSpaceBefore',
107 data: {
108 token: token.value,
109 },
110 fix(fixer) {
111 return fixer.insertTextBefore(token, ' ');
112 },
113 });
114 }
115 /**
116 * Determines if spacing in curly braces is valid.
117 * @param node The AST node to check.
118 * @param first The first token to check (should be the opening brace)
119 * @param second The second token to check (should be first after the opening brace)
120 * @param penultimate The penultimate token to check (should be last before closing brace)
121 * @param last The last token to check (should be closing brace)
122 */
123 function validateBraceSpacing(node, first, second, penultimate, last) {
124 if ((0, util_1.isTokenOnSameLine)(first, second)) {
125 const firstSpaced = sourceCode.isSpaceBetween(first, second);
126 const secondType = sourceCode.getNodeByRangeIndex(second.range[0]).type;
127 const openingCurlyBraceMustBeSpaced = options.arraysInObjectsException &&
128 [
129 utils_1.AST_NODE_TYPES.TSMappedType,
130 utils_1.AST_NODE_TYPES.TSIndexSignature,
131 ].includes(secondType)
132 ? !options.spaced
133 : options.spaced;
134 if (openingCurlyBraceMustBeSpaced && !firstSpaced) {
135 reportRequiredBeginningSpace(node, first);
136 }
137 if (!openingCurlyBraceMustBeSpaced &&
138 firstSpaced &&
139 second.type !== utils_1.AST_TOKEN_TYPES.Line) {
140 reportNoBeginningSpace(node, first);
141 }
142 }
143 if ((0, util_1.isTokenOnSameLine)(penultimate, last)) {
144 const shouldCheckPenultimate = (options.arraysInObjectsException &&
145 (0, util_1.isClosingBracketToken)(penultimate)) ||
146 (options.objectsInObjectsException &&
147 (0, util_1.isClosingBraceToken)(penultimate));
148 const penultimateType = shouldCheckPenultimate
149 ? sourceCode.getNodeByRangeIndex(penultimate.range[0]).type
150 : undefined;
151 const closingCurlyBraceMustBeSpaced = (options.arraysInObjectsException &&
152 penultimateType === utils_1.AST_NODE_TYPES.TSTupleType) ||
153 (options.objectsInObjectsException &&
154 penultimateType !== undefined &&
155 [
156 utils_1.AST_NODE_TYPES.TSMappedType,
157 utils_1.AST_NODE_TYPES.TSTypeLiteral,
158 ].includes(penultimateType))
159 ? !options.spaced
160 : options.spaced;
161 const lastSpaced = sourceCode.isSpaceBetween(penultimate, last);
162 if (closingCurlyBraceMustBeSpaced && !lastSpaced) {
163 reportRequiredEndingSpace(node, last);
164 }
165 if (!closingCurlyBraceMustBeSpaced && lastSpaced) {
166 reportNoEndingSpace(node, last);
167 }
168 }
169 }
170 /**
171 * Gets '}' token of an object node.
172 *
173 * Because the last token of object patterns might be a type annotation,
174 * this traverses tokens preceded by the last property, then returns the
175 * first '}' token.
176 * @param node The node to get. This node is an
177 * ObjectExpression or an ObjectPattern. And this node has one or
178 * more properties.
179 * @returns '}' token.
180 */
181 function getClosingBraceOfObject(node) {
182 const lastProperty = node.members[node.members.length - 1];
183 return sourceCode.getTokenAfter(lastProperty, util_1.isClosingBraceToken);
184 }
185 //--------------------------------------------------------------------------
186 // Public
187 //--------------------------------------------------------------------------
188 const rules = baseRule.create(context);
189 return Object.assign(Object.assign({}, rules), { TSMappedType(node) {
190 const first = sourceCode.getFirstToken(node);
191 const last = sourceCode.getLastToken(node);
192 const second = sourceCode.getTokenAfter(first, {
193 includeComments: true,
194 });
195 const penultimate = sourceCode.getTokenBefore(last, {
196 includeComments: true,
197 });
198 validateBraceSpacing(node, first, second, penultimate, last);
199 },
200 TSTypeLiteral(node) {
201 if (node.members.length === 0) {
202 return;
203 }
204 const first = sourceCode.getFirstToken(node);
205 const last = getClosingBraceOfObject(node);
206 const second = sourceCode.getTokenAfter(first, {
207 includeComments: true,
208 });
209 const penultimate = sourceCode.getTokenBefore(last, {
210 includeComments: true,
211 });
212 validateBraceSpacing(node, first, second, penultimate, last);
213 } });
214 },
215});
216//# sourceMappingURL=object-curly-spacing.js.map
\No newline at end of file