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.

lines-around-directive.js 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /**
  2. * @fileoverview Require or disallow newlines around directives.
  3. * @author Kai Cataldo
  4. * @deprecated
  5. */
  6. "use strict";
  7. const astUtils = require("../util/ast-utils");
  8. //------------------------------------------------------------------------------
  9. // Rule Definition
  10. //------------------------------------------------------------------------------
  11. module.exports = {
  12. meta: {
  13. type: "layout",
  14. docs: {
  15. description: "require or disallow newlines around directives",
  16. category: "Stylistic Issues",
  17. recommended: false,
  18. url: "https://eslint.org/docs/rules/lines-around-directive"
  19. },
  20. schema: [{
  21. oneOf: [
  22. {
  23. enum: ["always", "never"]
  24. },
  25. {
  26. type: "object",
  27. properties: {
  28. before: {
  29. enum: ["always", "never"]
  30. },
  31. after: {
  32. enum: ["always", "never"]
  33. }
  34. },
  35. additionalProperties: false,
  36. minProperties: 2
  37. }
  38. ]
  39. }],
  40. fixable: "whitespace",
  41. deprecated: true,
  42. replacedBy: ["padding-line-between-statements"]
  43. },
  44. create(context) {
  45. const sourceCode = context.getSourceCode();
  46. const config = context.options[0] || "always";
  47. const expectLineBefore = typeof config === "string" ? config : config.before;
  48. const expectLineAfter = typeof config === "string" ? config : config.after;
  49. //--------------------------------------------------------------------------
  50. // Helpers
  51. //--------------------------------------------------------------------------
  52. /**
  53. * Check if node is preceded by a blank newline.
  54. * @param {ASTNode} node Node to check.
  55. * @returns {boolean} Whether or not the passed in node is preceded by a blank newline.
  56. */
  57. function hasNewlineBefore(node) {
  58. const tokenBefore = sourceCode.getTokenBefore(node, { includeComments: true });
  59. const tokenLineBefore = tokenBefore ? tokenBefore.loc.end.line : 0;
  60. return node.loc.start.line - tokenLineBefore >= 2;
  61. }
  62. /**
  63. * Gets the last token of a node that is on the same line as the rest of the node.
  64. * This will usually be the last token of the node, but it will be the second-to-last token if the node has a trailing
  65. * semicolon on a different line.
  66. * @param {ASTNode} node A directive node
  67. * @returns {Token} The last token of the node on the line
  68. */
  69. function getLastTokenOnLine(node) {
  70. const lastToken = sourceCode.getLastToken(node);
  71. const secondToLastToken = sourceCode.getTokenBefore(lastToken);
  72. return astUtils.isSemicolonToken(lastToken) && lastToken.loc.start.line > secondToLastToken.loc.end.line
  73. ? secondToLastToken
  74. : lastToken;
  75. }
  76. /**
  77. * Check if node is followed by a blank newline.
  78. * @param {ASTNode} node Node to check.
  79. * @returns {boolean} Whether or not the passed in node is followed by a blank newline.
  80. */
  81. function hasNewlineAfter(node) {
  82. const lastToken = getLastTokenOnLine(node);
  83. const tokenAfter = sourceCode.getTokenAfter(lastToken, { includeComments: true });
  84. return tokenAfter.loc.start.line - lastToken.loc.end.line >= 2;
  85. }
  86. /**
  87. * Report errors for newlines around directives.
  88. * @param {ASTNode} node Node to check.
  89. * @param {string} location Whether the error was found before or after the directive.
  90. * @param {boolean} expected Whether or not a newline was expected or unexpected.
  91. * @returns {void}
  92. */
  93. function reportError(node, location, expected) {
  94. context.report({
  95. node,
  96. message: "{{expected}} newline {{location}} \"{{value}}\" directive.",
  97. data: {
  98. expected: expected ? "Expected" : "Unexpected",
  99. value: node.expression.value,
  100. location
  101. },
  102. fix(fixer) {
  103. const lastToken = getLastTokenOnLine(node);
  104. if (expected) {
  105. return location === "before" ? fixer.insertTextBefore(node, "\n") : fixer.insertTextAfter(lastToken, "\n");
  106. }
  107. return fixer.removeRange(location === "before" ? [node.range[0] - 1, node.range[0]] : [lastToken.range[1], lastToken.range[1] + 1]);
  108. }
  109. });
  110. }
  111. /**
  112. * Check lines around directives in node
  113. * @param {ASTNode} node - node to check
  114. * @returns {void}
  115. */
  116. function checkDirectives(node) {
  117. const directives = astUtils.getDirectivePrologue(node);
  118. if (!directives.length) {
  119. return;
  120. }
  121. const firstDirective = directives[0];
  122. const leadingComments = sourceCode.getCommentsBefore(firstDirective);
  123. /*
  124. * Only check before the first directive if it is preceded by a comment or if it is at the top of
  125. * the file and expectLineBefore is set to "never". This is to not force a newline at the top of
  126. * the file if there are no comments as well as for compatibility with padded-blocks.
  127. */
  128. if (leadingComments.length) {
  129. if (expectLineBefore === "always" && !hasNewlineBefore(firstDirective)) {
  130. reportError(firstDirective, "before", true);
  131. }
  132. if (expectLineBefore === "never" && hasNewlineBefore(firstDirective)) {
  133. reportError(firstDirective, "before", false);
  134. }
  135. } else if (
  136. node.type === "Program" &&
  137. expectLineBefore === "never" &&
  138. !leadingComments.length &&
  139. hasNewlineBefore(firstDirective)
  140. ) {
  141. reportError(firstDirective, "before", false);
  142. }
  143. const lastDirective = directives[directives.length - 1];
  144. const statements = node.type === "Program" ? node.body : node.body.body;
  145. /*
  146. * Do not check after the last directive if the body only
  147. * contains a directive prologue and isn't followed by a comment to ensure
  148. * this rule behaves well with padded-blocks.
  149. */
  150. if (lastDirective === statements[statements.length - 1] && !lastDirective.trailingComments) {
  151. return;
  152. }
  153. if (expectLineAfter === "always" && !hasNewlineAfter(lastDirective)) {
  154. reportError(lastDirective, "after", true);
  155. }
  156. if (expectLineAfter === "never" && hasNewlineAfter(lastDirective)) {
  157. reportError(lastDirective, "after", false);
  158. }
  159. }
  160. //--------------------------------------------------------------------------
  161. // Public
  162. //--------------------------------------------------------------------------
  163. return {
  164. Program: checkDirectives,
  165. FunctionDeclaration: checkDirectives,
  166. FunctionExpression: checkDirectives,
  167. ArrowFunctionExpression: checkDirectives
  168. };
  169. }
  170. };