Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

generator-star-spacing.js 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /**
  2. * @fileoverview Rule to check the spacing around the * in generator functions.
  3. * @author Jamund Ferguson
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Rule Definition
  8. //------------------------------------------------------------------------------
  9. const OVERRIDE_SCHEMA = {
  10. oneOf: [
  11. {
  12. enum: ["before", "after", "both", "neither"]
  13. },
  14. {
  15. type: "object",
  16. properties: {
  17. before: { type: "boolean" },
  18. after: { type: "boolean" }
  19. },
  20. additionalProperties: false
  21. }
  22. ]
  23. };
  24. module.exports = {
  25. meta: {
  26. type: "layout",
  27. docs: {
  28. description: "enforce consistent spacing around `*` operators in generator functions",
  29. category: "ECMAScript 6",
  30. recommended: false,
  31. url: "https://eslint.org/docs/rules/generator-star-spacing"
  32. },
  33. fixable: "whitespace",
  34. schema: [
  35. {
  36. oneOf: [
  37. {
  38. enum: ["before", "after", "both", "neither"]
  39. },
  40. {
  41. type: "object",
  42. properties: {
  43. before: { type: "boolean" },
  44. after: { type: "boolean" },
  45. named: OVERRIDE_SCHEMA,
  46. anonymous: OVERRIDE_SCHEMA,
  47. method: OVERRIDE_SCHEMA
  48. },
  49. additionalProperties: false
  50. }
  51. ]
  52. }
  53. ],
  54. messages: {
  55. missingBefore: "Missing space before *.",
  56. missingAfter: "Missing space after *.",
  57. unexpectedBefore: "Unexpected space before *.",
  58. unexpectedAfter: "Unexpected space after *."
  59. }
  60. },
  61. create(context) {
  62. const optionDefinitions = {
  63. before: { before: true, after: false },
  64. after: { before: false, after: true },
  65. both: { before: true, after: true },
  66. neither: { before: false, after: false }
  67. };
  68. /**
  69. * Returns resolved option definitions based on an option and defaults
  70. *
  71. * @param {any} option - The option object or string value
  72. * @param {Object} defaults - The defaults to use if options are not present
  73. * @returns {Object} the resolved object definition
  74. */
  75. function optionToDefinition(option, defaults) {
  76. if (!option) {
  77. return defaults;
  78. }
  79. return typeof option === "string"
  80. ? optionDefinitions[option]
  81. : Object.assign({}, defaults, option);
  82. }
  83. const modes = (function(option) {
  84. const defaults = optionToDefinition(option, optionDefinitions.before);
  85. return {
  86. named: optionToDefinition(option.named, defaults),
  87. anonymous: optionToDefinition(option.anonymous, defaults),
  88. method: optionToDefinition(option.method, defaults)
  89. };
  90. }(context.options[0] || {}));
  91. const sourceCode = context.getSourceCode();
  92. /**
  93. * Checks if the given token is a star token or not.
  94. *
  95. * @param {Token} token - The token to check.
  96. * @returns {boolean} `true` if the token is a star token.
  97. */
  98. function isStarToken(token) {
  99. return token.value === "*" && token.type === "Punctuator";
  100. }
  101. /**
  102. * Gets the generator star token of the given function node.
  103. *
  104. * @param {ASTNode} node - The function node to get.
  105. * @returns {Token} Found star token.
  106. */
  107. function getStarToken(node) {
  108. return sourceCode.getFirstToken(
  109. (node.parent.method || node.parent.type === "MethodDefinition") ? node.parent : node,
  110. isStarToken
  111. );
  112. }
  113. /**
  114. * capitalize a given string.
  115. * @param {string} str the given string.
  116. * @returns {string} the capitalized string.
  117. */
  118. function capitalize(str) {
  119. return str[0].toUpperCase() + str.slice(1);
  120. }
  121. /**
  122. * Checks the spacing between two tokens before or after the star token.
  123. *
  124. * @param {string} kind Either "named", "anonymous", or "method"
  125. * @param {string} side Either "before" or "after".
  126. * @param {Token} leftToken `function` keyword token if side is "before", or
  127. * star token if side is "after".
  128. * @param {Token} rightToken Star token if side is "before", or identifier
  129. * token if side is "after".
  130. * @returns {void}
  131. */
  132. function checkSpacing(kind, side, leftToken, rightToken) {
  133. if (!!(rightToken.range[0] - leftToken.range[1]) !== modes[kind][side]) {
  134. const after = leftToken.value === "*";
  135. const spaceRequired = modes[kind][side];
  136. const node = after ? leftToken : rightToken;
  137. const messageId = `${spaceRequired ? "missing" : "unexpected"}${capitalize(side)}`;
  138. context.report({
  139. node,
  140. messageId,
  141. fix(fixer) {
  142. if (spaceRequired) {
  143. if (after) {
  144. return fixer.insertTextAfter(node, " ");
  145. }
  146. return fixer.insertTextBefore(node, " ");
  147. }
  148. return fixer.removeRange([leftToken.range[1], rightToken.range[0]]);
  149. }
  150. });
  151. }
  152. }
  153. /**
  154. * Enforces the spacing around the star if node is a generator function.
  155. *
  156. * @param {ASTNode} node A function expression or declaration node.
  157. * @returns {void}
  158. */
  159. function checkFunction(node) {
  160. if (!node.generator) {
  161. return;
  162. }
  163. const starToken = getStarToken(node);
  164. const prevToken = sourceCode.getTokenBefore(starToken);
  165. const nextToken = sourceCode.getTokenAfter(starToken);
  166. let kind = "named";
  167. if (node.parent.type === "MethodDefinition" || (node.parent.type === "Property" && node.parent.method)) {
  168. kind = "method";
  169. } else if (!node.id) {
  170. kind = "anonymous";
  171. }
  172. // Only check before when preceded by `function`|`static` keyword
  173. if (!(kind === "method" && starToken === sourceCode.getFirstToken(node.parent))) {
  174. checkSpacing(kind, "before", prevToken, starToken);
  175. }
  176. checkSpacing(kind, "after", starToken, nextToken);
  177. }
  178. return {
  179. FunctionDeclaration: checkFunction,
  180. FunctionExpression: checkFunction
  181. };
  182. }
  183. };