computed-property-spacing.js 6.6 KB

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