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.

brace-style.js 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /**
  2. * @fileoverview Rule to flag block statements that do not use the one true brace style
  3. * @author Ian Christian Myers
  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 brace style for blocks",
  15. category: "Stylistic Issues",
  16. recommended: false,
  17. url: "https://eslint.org/docs/rules/brace-style"
  18. },
  19. schema: [
  20. {
  21. enum: ["1tbs", "stroustrup", "allman"]
  22. },
  23. {
  24. type: "object",
  25. properties: {
  26. allowSingleLine: {
  27. type: "boolean"
  28. }
  29. },
  30. additionalProperties: false
  31. }
  32. ],
  33. fixable: "whitespace",
  34. messages: {
  35. nextLineOpen: "Opening curly brace does not appear on the same line as controlling statement.",
  36. sameLineOpen: "Opening curly brace appears on the same line as controlling statement.",
  37. blockSameLine: "Statement inside of curly braces should be on next line.",
  38. nextLineClose: "Closing curly brace does not appear on the same line as the subsequent block.",
  39. singleLineClose: "Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.",
  40. sameLineClose: "Closing curly brace appears on the same line as the subsequent block."
  41. }
  42. },
  43. create(context) {
  44. const style = context.options[0] || "1tbs",
  45. params = context.options[1] || {},
  46. sourceCode = context.getSourceCode();
  47. //--------------------------------------------------------------------------
  48. // Helpers
  49. //--------------------------------------------------------------------------
  50. /**
  51. * Fixes a place where a newline unexpectedly appears
  52. * @param {Token} firstToken The token before the unexpected newline
  53. * @param {Token} secondToken The token after the unexpected newline
  54. * @returns {Function} A fixer function to remove the newlines between the tokens
  55. */
  56. function removeNewlineBetween(firstToken, secondToken) {
  57. const textRange = [firstToken.range[1], secondToken.range[0]];
  58. const textBetween = sourceCode.text.slice(textRange[0], textRange[1]);
  59. // Don't do a fix if there is a comment between the tokens
  60. if (textBetween.trim()) {
  61. return null;
  62. }
  63. return fixer => fixer.replaceTextRange(textRange, " ");
  64. }
  65. /**
  66. * Validates a pair of curly brackets based on the user's config
  67. * @param {Token} openingCurly The opening curly bracket
  68. * @param {Token} closingCurly The closing curly bracket
  69. * @returns {void}
  70. */
  71. function validateCurlyPair(openingCurly, closingCurly) {
  72. const tokenBeforeOpeningCurly = sourceCode.getTokenBefore(openingCurly);
  73. const tokenAfterOpeningCurly = sourceCode.getTokenAfter(openingCurly);
  74. const tokenBeforeClosingCurly = sourceCode.getTokenBefore(closingCurly);
  75. const singleLineException = params.allowSingleLine && astUtils.isTokenOnSameLine(openingCurly, closingCurly);
  76. if (style !== "allman" && !astUtils.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurly)) {
  77. context.report({
  78. node: openingCurly,
  79. messageId: "nextLineOpen",
  80. fix: removeNewlineBetween(tokenBeforeOpeningCurly, openingCurly)
  81. });
  82. }
  83. if (style === "allman" && astUtils.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurly) && !singleLineException) {
  84. context.report({
  85. node: openingCurly,
  86. messageId: "sameLineOpen",
  87. fix: fixer => fixer.insertTextBefore(openingCurly, "\n")
  88. });
  89. }
  90. if (astUtils.isTokenOnSameLine(openingCurly, tokenAfterOpeningCurly) && tokenAfterOpeningCurly !== closingCurly && !singleLineException) {
  91. context.report({
  92. node: openingCurly,
  93. messageId: "blockSameLine",
  94. fix: fixer => fixer.insertTextAfter(openingCurly, "\n")
  95. });
  96. }
  97. if (tokenBeforeClosingCurly !== openingCurly && !singleLineException && astUtils.isTokenOnSameLine(tokenBeforeClosingCurly, closingCurly)) {
  98. context.report({
  99. node: closingCurly,
  100. messageId: "singleLineClose",
  101. fix: fixer => fixer.insertTextBefore(closingCurly, "\n")
  102. });
  103. }
  104. }
  105. /**
  106. * Validates the location of a token that appears before a keyword (e.g. a newline before `else`)
  107. * @param {Token} curlyToken The closing curly token. This is assumed to precede a keyword token (such as `else` or `finally`).
  108. * @returns {void}
  109. */
  110. function validateCurlyBeforeKeyword(curlyToken) {
  111. const keywordToken = sourceCode.getTokenAfter(curlyToken);
  112. if (style === "1tbs" && !astUtils.isTokenOnSameLine(curlyToken, keywordToken)) {
  113. context.report({
  114. node: curlyToken,
  115. messageId: "nextLineClose",
  116. fix: removeNewlineBetween(curlyToken, keywordToken)
  117. });
  118. }
  119. if (style !== "1tbs" && astUtils.isTokenOnSameLine(curlyToken, keywordToken)) {
  120. context.report({
  121. node: curlyToken,
  122. messageId: "sameLineClose",
  123. fix: fixer => fixer.insertTextAfter(curlyToken, "\n")
  124. });
  125. }
  126. }
  127. //--------------------------------------------------------------------------
  128. // Public API
  129. //--------------------------------------------------------------------------
  130. return {
  131. BlockStatement(node) {
  132. if (!astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)) {
  133. validateCurlyPair(sourceCode.getFirstToken(node), sourceCode.getLastToken(node));
  134. }
  135. },
  136. ClassBody(node) {
  137. validateCurlyPair(sourceCode.getFirstToken(node), sourceCode.getLastToken(node));
  138. },
  139. SwitchStatement(node) {
  140. const closingCurly = sourceCode.getLastToken(node);
  141. const openingCurly = sourceCode.getTokenBefore(node.cases.length ? node.cases[0] : closingCurly);
  142. validateCurlyPair(openingCurly, closingCurly);
  143. },
  144. IfStatement(node) {
  145. if (node.consequent.type === "BlockStatement" && node.alternate) {
  146. // Handle the keyword after the `if` block (before `else`)
  147. validateCurlyBeforeKeyword(sourceCode.getLastToken(node.consequent));
  148. }
  149. },
  150. TryStatement(node) {
  151. // Handle the keyword after the `try` block (before `catch` or `finally`)
  152. validateCurlyBeforeKeyword(sourceCode.getLastToken(node.block));
  153. if (node.handler && node.finalizer) {
  154. // Handle the keyword after the `catch` block (before `finally`)
  155. validateCurlyBeforeKeyword(sourceCode.getLastToken(node.handler.body));
  156. }
  157. }
  158. };
  159. }
  160. };