rest-spread-spacing.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /**
  2. * @fileoverview Enforce spacing between rest and spread operators and their expressions.
  3. * @author Kai Cataldo
  4. * @deprecated in ESLint v8.53.0
  5. */
  6. "use strict";
  7. //------------------------------------------------------------------------------
  8. // Rule Definition
  9. //------------------------------------------------------------------------------
  10. /** @type {import('../types').Rule.RuleModule} */
  11. module.exports = {
  12. meta: {
  13. deprecated: {
  14. message: "Formatting rules are being moved out of ESLint core.",
  15. url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
  16. deprecatedSince: "8.53.0",
  17. availableUntil: "11.0.0",
  18. replacedBy: [
  19. {
  20. message:
  21. "ESLint Stylistic now maintains deprecated stylistic core rules.",
  22. url: "https://eslint.style/guide/migration",
  23. plugin: {
  24. name: "@stylistic/eslint-plugin",
  25. url: "https://eslint.style",
  26. },
  27. rule: {
  28. name: "rest-spread-spacing",
  29. url: "https://eslint.style/rules/rest-spread-spacing",
  30. },
  31. },
  32. ],
  33. },
  34. type: "layout",
  35. docs: {
  36. description:
  37. "Enforce spacing between rest and spread operators and their expressions",
  38. recommended: false,
  39. url: "https://eslint.org/docs/latest/rules/rest-spread-spacing",
  40. },
  41. fixable: "whitespace",
  42. schema: [
  43. {
  44. enum: ["always", "never"],
  45. },
  46. ],
  47. messages: {
  48. unexpectedWhitespace:
  49. "Unexpected whitespace after {{type}} operator.",
  50. expectedWhitespace: "Expected whitespace after {{type}} operator.",
  51. },
  52. },
  53. create(context) {
  54. const sourceCode = context.sourceCode,
  55. alwaysSpace = context.options[0] === "always";
  56. //--------------------------------------------------------------------------
  57. // Helpers
  58. //--------------------------------------------------------------------------
  59. /**
  60. * Checks whitespace between rest/spread operators and their expressions
  61. * @param {ASTNode} node The node to check
  62. * @returns {void}
  63. */
  64. function checkWhiteSpace(node) {
  65. const operator = sourceCode.getFirstToken(node),
  66. nextToken = sourceCode.getTokenAfter(operator),
  67. hasWhitespace = sourceCode.isSpaceBetweenTokens(
  68. operator,
  69. nextToken,
  70. );
  71. let type;
  72. switch (node.type) {
  73. case "SpreadElement":
  74. type = "spread";
  75. if (node.parent.type === "ObjectExpression") {
  76. type += " property";
  77. }
  78. break;
  79. case "RestElement":
  80. type = "rest";
  81. if (node.parent.type === "ObjectPattern") {
  82. type += " property";
  83. }
  84. break;
  85. case "ExperimentalSpreadProperty":
  86. type = "spread property";
  87. break;
  88. case "ExperimentalRestProperty":
  89. type = "rest property";
  90. break;
  91. default:
  92. return;
  93. }
  94. if (alwaysSpace && !hasWhitespace) {
  95. context.report({
  96. node,
  97. loc: operator.loc,
  98. messageId: "expectedWhitespace",
  99. data: {
  100. type,
  101. },
  102. fix(fixer) {
  103. return fixer.replaceTextRange(
  104. [operator.range[1], nextToken.range[0]],
  105. " ",
  106. );
  107. },
  108. });
  109. } else if (!alwaysSpace && hasWhitespace) {
  110. context.report({
  111. node,
  112. loc: {
  113. start: operator.loc.end,
  114. end: nextToken.loc.start,
  115. },
  116. messageId: "unexpectedWhitespace",
  117. data: {
  118. type,
  119. },
  120. fix(fixer) {
  121. return fixer.removeRange([
  122. operator.range[1],
  123. nextToken.range[0],
  124. ]);
  125. },
  126. });
  127. }
  128. }
  129. //--------------------------------------------------------------------------
  130. // Public
  131. //--------------------------------------------------------------------------
  132. return {
  133. SpreadElement: checkWhiteSpace,
  134. RestElement: checkWhiteSpace,
  135. ExperimentalSpreadProperty: checkWhiteSpace,
  136. ExperimentalRestProperty: checkWhiteSpace,
  137. };
  138. },
  139. };