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.

semi-spacing.js 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /**
  2. * @fileoverview Validates spacing before and after semicolon
  3. * @author Mathias Schreck
  4. */
  5. "use strict";
  6. const astUtils = require("../util/ast-utils");
  7. //------------------------------------------------------------------------------
  8. // Rule Definition
  9. //------------------------------------------------------------------------------
  10. module.exports = {
  11. meta: {
  12. type: "layout",
  13. docs: {
  14. description: "enforce consistent spacing before and after semicolons",
  15. category: "Stylistic Issues",
  16. recommended: false,
  17. url: "https://eslint.org/docs/rules/semi-spacing"
  18. },
  19. fixable: "whitespace",
  20. schema: [
  21. {
  22. type: "object",
  23. properties: {
  24. before: {
  25. type: "boolean"
  26. },
  27. after: {
  28. type: "boolean"
  29. }
  30. },
  31. additionalProperties: false
  32. }
  33. ]
  34. },
  35. create(context) {
  36. const config = context.options[0],
  37. sourceCode = context.getSourceCode();
  38. let requireSpaceBefore = false,
  39. requireSpaceAfter = true;
  40. if (typeof config === "object") {
  41. if (Object.prototype.hasOwnProperty.call(config, "before")) {
  42. requireSpaceBefore = config.before;
  43. }
  44. if (Object.prototype.hasOwnProperty.call(config, "after")) {
  45. requireSpaceAfter = config.after;
  46. }
  47. }
  48. /**
  49. * Checks if a given token has leading whitespace.
  50. * @param {Object} token The token to check.
  51. * @returns {boolean} True if the given token has leading space, false if not.
  52. */
  53. function hasLeadingSpace(token) {
  54. const tokenBefore = sourceCode.getTokenBefore(token);
  55. return tokenBefore && astUtils.isTokenOnSameLine(tokenBefore, token) && sourceCode.isSpaceBetweenTokens(tokenBefore, token);
  56. }
  57. /**
  58. * Checks if a given token has trailing whitespace.
  59. * @param {Object} token The token to check.
  60. * @returns {boolean} True if the given token has trailing space, false if not.
  61. */
  62. function hasTrailingSpace(token) {
  63. const tokenAfter = sourceCode.getTokenAfter(token);
  64. return tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter) && sourceCode.isSpaceBetweenTokens(token, tokenAfter);
  65. }
  66. /**
  67. * Checks if the given token is the last token in its line.
  68. * @param {Token} token The token to check.
  69. * @returns {boolean} Whether or not the token is the last in its line.
  70. */
  71. function isLastTokenInCurrentLine(token) {
  72. const tokenAfter = sourceCode.getTokenAfter(token);
  73. return !(tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter));
  74. }
  75. /**
  76. * Checks if the given token is the first token in its line
  77. * @param {Token} token The token to check.
  78. * @returns {boolean} Whether or not the token is the first in its line.
  79. */
  80. function isFirstTokenInCurrentLine(token) {
  81. const tokenBefore = sourceCode.getTokenBefore(token);
  82. return !(tokenBefore && astUtils.isTokenOnSameLine(token, tokenBefore));
  83. }
  84. /**
  85. * Checks if the next token of a given token is a closing parenthesis.
  86. * @param {Token} token The token to check.
  87. * @returns {boolean} Whether or not the next token of a given token is a closing parenthesis.
  88. */
  89. function isBeforeClosingParen(token) {
  90. const nextToken = sourceCode.getTokenAfter(token);
  91. return (nextToken && astUtils.isClosingBraceToken(nextToken) || astUtils.isClosingParenToken(nextToken));
  92. }
  93. /**
  94. * Reports if the given token has invalid spacing.
  95. * @param {Token} token The semicolon token to check.
  96. * @param {ASTNode} node The corresponding node of the token.
  97. * @returns {void}
  98. */
  99. function checkSemicolonSpacing(token, node) {
  100. if (astUtils.isSemicolonToken(token)) {
  101. const location = token.loc.start;
  102. if (hasLeadingSpace(token)) {
  103. if (!requireSpaceBefore) {
  104. context.report({
  105. node,
  106. loc: location,
  107. message: "Unexpected whitespace before semicolon.",
  108. fix(fixer) {
  109. const tokenBefore = sourceCode.getTokenBefore(token);
  110. return fixer.removeRange([tokenBefore.range[1], token.range[0]]);
  111. }
  112. });
  113. }
  114. } else {
  115. if (requireSpaceBefore) {
  116. context.report({
  117. node,
  118. loc: location,
  119. message: "Missing whitespace before semicolon.",
  120. fix(fixer) {
  121. return fixer.insertTextBefore(token, " ");
  122. }
  123. });
  124. }
  125. }
  126. if (!isFirstTokenInCurrentLine(token) && !isLastTokenInCurrentLine(token) && !isBeforeClosingParen(token)) {
  127. if (hasTrailingSpace(token)) {
  128. if (!requireSpaceAfter) {
  129. context.report({
  130. node,
  131. loc: location,
  132. message: "Unexpected whitespace after semicolon.",
  133. fix(fixer) {
  134. const tokenAfter = sourceCode.getTokenAfter(token);
  135. return fixer.removeRange([token.range[1], tokenAfter.range[0]]);
  136. }
  137. });
  138. }
  139. } else {
  140. if (requireSpaceAfter) {
  141. context.report({
  142. node,
  143. loc: location,
  144. message: "Missing whitespace after semicolon.",
  145. fix(fixer) {
  146. return fixer.insertTextAfter(token, " ");
  147. }
  148. });
  149. }
  150. }
  151. }
  152. }
  153. }
  154. /**
  155. * Checks the spacing of the semicolon with the assumption that the last token is the semicolon.
  156. * @param {ASTNode} node The node to check.
  157. * @returns {void}
  158. */
  159. function checkNode(node) {
  160. const token = sourceCode.getLastToken(node);
  161. checkSemicolonSpacing(token, node);
  162. }
  163. return {
  164. VariableDeclaration: checkNode,
  165. ExpressionStatement: checkNode,
  166. BreakStatement: checkNode,
  167. ContinueStatement: checkNode,
  168. DebuggerStatement: checkNode,
  169. ReturnStatement: checkNode,
  170. ThrowStatement: checkNode,
  171. ImportDeclaration: checkNode,
  172. ExportNamedDeclaration: checkNode,
  173. ExportAllDeclaration: checkNode,
  174. ExportDefaultDeclaration: checkNode,
  175. ForStatement(node) {
  176. if (node.init) {
  177. checkSemicolonSpacing(sourceCode.getTokenAfter(node.init), node);
  178. }
  179. if (node.test) {
  180. checkSemicolonSpacing(sourceCode.getTokenAfter(node.test), node);
  181. }
  182. }
  183. };
  184. }
  185. };