UNPKG

6.75 kBJavaScriptView Raw
1/**
2 * @fileoverview Disallows or enforces spaces inside computed properties.
3 * @author Jamund Ferguson
4 */
5"use strict";
6
7const astUtils = require("../ast-utils");
8
9//------------------------------------------------------------------------------
10// Rule Definition
11//------------------------------------------------------------------------------
12
13module.exports = {
14 meta: {
15 docs: {
16 description: "enforce consistent spacing inside computed property brackets",
17 category: "Stylistic Issues",
18 recommended: false,
19 url: "https://eslint.org/docs/rules/computed-property-spacing"
20 },
21
22 fixable: "whitespace",
23
24 schema: [
25 {
26 enum: ["always", "never"]
27 }
28 ],
29
30 messages: {
31 unexpectedSpaceBefore: "There should be no space before '{{tokenValue}}'.",
32 unexpectedSpaceAfter: "There should be no space after '{{tokenValue}}'.",
33
34 missingSpaceBefore: "A space is required before '{{tokenValue}}'.",
35 missingSpaceAfter: "A space is required after '{{tokenValue}}'."
36 }
37 },
38
39 create(context) {
40 const sourceCode = context.getSourceCode();
41 const propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never"
42
43 //--------------------------------------------------------------------------
44 // Helpers
45 //--------------------------------------------------------------------------
46
47 /**
48 * Reports that there shouldn't be a space after the first token
49 * @param {ASTNode} node - The node to report in the event of an error.
50 * @param {Token} token - The token to use for the report.
51 * @param {Token} tokenAfter - The token after `token`.
52 * @returns {void}
53 */
54 function reportNoBeginningSpace(node, token, tokenAfter) {
55 context.report({
56 node,
57 loc: token.loc.start,
58 messageId: "unexpectedSpaceAfter",
59 data: {
60 tokenValue: token.value
61 },
62 fix(fixer) {
63 return fixer.removeRange([token.range[1], tokenAfter.range[0]]);
64 }
65 });
66 }
67
68 /**
69 * Reports that there shouldn't be a space before the last token
70 * @param {ASTNode} node - The node to report in the event of an error.
71 * @param {Token} token - The token to use for the report.
72 * @param {Token} tokenBefore - The token before `token`.
73 * @returns {void}
74 */
75 function reportNoEndingSpace(node, token, tokenBefore) {
76 context.report({
77 node,
78 loc: token.loc.start,
79 messageId: "unexpectedSpaceBefore",
80 data: {
81 tokenValue: token.value
82 },
83 fix(fixer) {
84 return fixer.removeRange([tokenBefore.range[1], token.range[0]]);
85 }
86 });
87 }
88
89 /**
90 * Reports that there should be a space after the first token
91 * @param {ASTNode} node - The node to report in the event of an error.
92 * @param {Token} token - The token to use for the report.
93 * @returns {void}
94 */
95 function reportRequiredBeginningSpace(node, token) {
96 context.report({
97 node,
98 loc: token.loc.start,
99 messageId: "missingSpaceAfter",
100 data: {
101 tokenValue: token.value
102 },
103 fix(fixer) {
104 return fixer.insertTextAfter(token, " ");
105 }
106 });
107 }
108
109 /**
110 * Reports that there should be a space before the last token
111 * @param {ASTNode} node - The node to report in the event of an error.
112 * @param {Token} token - The token to use for the report.
113 * @returns {void}
114 */
115 function reportRequiredEndingSpace(node, token) {
116 context.report({
117 node,
118 loc: token.loc.start,
119 messageId: "missingSpaceBefore",
120 data: {
121 tokenValue: token.value
122 },
123 fix(fixer) {
124 return fixer.insertTextBefore(token, " ");
125 }
126 });
127 }
128
129 /**
130 * Returns a function that checks the spacing of a node on the property name
131 * that was passed in.
132 * @param {string} propertyName The property on the node to check for spacing
133 * @returns {Function} A function that will check spacing on a node
134 */
135 function checkSpacing(propertyName) {
136 return function(node) {
137 if (!node.computed) {
138 return;
139 }
140
141 const property = node[propertyName];
142
143 const before = sourceCode.getTokenBefore(property),
144 first = sourceCode.getFirstToken(property),
145 last = sourceCode.getLastToken(property),
146 after = sourceCode.getTokenAfter(property);
147
148 if (astUtils.isTokenOnSameLine(before, first)) {
149 if (propertyNameMustBeSpaced) {
150 if (!sourceCode.isSpaceBetweenTokens(before, first) && astUtils.isTokenOnSameLine(before, first)) {
151 reportRequiredBeginningSpace(node, before);
152 }
153 } else {
154 if (sourceCode.isSpaceBetweenTokens(before, first)) {
155 reportNoBeginningSpace(node, before, first);
156 }
157 }
158 }
159
160 if (astUtils.isTokenOnSameLine(last, after)) {
161 if (propertyNameMustBeSpaced) {
162 if (!sourceCode.isSpaceBetweenTokens(last, after) && astUtils.isTokenOnSameLine(last, after)) {
163 reportRequiredEndingSpace(node, after);
164 }
165 } else {
166 if (sourceCode.isSpaceBetweenTokens(last, after)) {
167 reportNoEndingSpace(node, after, last);
168 }
169 }
170 }
171 };
172 }
173
174
175 //--------------------------------------------------------------------------
176 // Public
177 //--------------------------------------------------------------------------
178
179 return {
180 Property: checkSpacing("key"),
181 MemberExpression: checkSpacing("property")
182 };
183
184 }
185};