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.

array-bracket-newline.js 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /**
  2. * @fileoverview Rule to enforce linebreaks after open and before close array brackets
  3. * @author Jan Peer Stöcklmair <https://github.com/JPeer264>
  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 linebreaks after opening and before closing array brackets",
  15. category: "Stylistic Issues",
  16. recommended: false,
  17. url: "https://eslint.org/docs/rules/array-bracket-newline"
  18. },
  19. fixable: "whitespace",
  20. schema: [
  21. {
  22. oneOf: [
  23. {
  24. enum: ["always", "never", "consistent"]
  25. },
  26. {
  27. type: "object",
  28. properties: {
  29. multiline: {
  30. type: "boolean"
  31. },
  32. minItems: {
  33. type: ["integer", "null"],
  34. minimum: 0
  35. }
  36. },
  37. additionalProperties: false
  38. }
  39. ]
  40. }
  41. ],
  42. messages: {
  43. unexpectedOpeningLinebreak: "There should be no linebreak after '['.",
  44. unexpectedClosingLinebreak: "There should be no linebreak before ']'.",
  45. missingOpeningLinebreak: "A linebreak is required after '['.",
  46. missingClosingLinebreak: "A linebreak is required before ']'."
  47. }
  48. },
  49. create(context) {
  50. const sourceCode = context.getSourceCode();
  51. //----------------------------------------------------------------------
  52. // Helpers
  53. //----------------------------------------------------------------------
  54. /**
  55. * Normalizes a given option value.
  56. *
  57. * @param {string|Object|undefined} option - An option value to parse.
  58. * @returns {{multiline: boolean, minItems: number}} Normalized option object.
  59. */
  60. function normalizeOptionValue(option) {
  61. let consistent = false;
  62. let multiline = false;
  63. let minItems = 0;
  64. if (option) {
  65. if (option === "consistent") {
  66. consistent = true;
  67. minItems = Number.POSITIVE_INFINITY;
  68. } else if (option === "always" || option.minItems === 0) {
  69. minItems = 0;
  70. } else if (option === "never") {
  71. minItems = Number.POSITIVE_INFINITY;
  72. } else {
  73. multiline = Boolean(option.multiline);
  74. minItems = option.minItems || Number.POSITIVE_INFINITY;
  75. }
  76. } else {
  77. consistent = false;
  78. multiline = true;
  79. minItems = Number.POSITIVE_INFINITY;
  80. }
  81. return { consistent, multiline, minItems };
  82. }
  83. /**
  84. * Normalizes a given option value.
  85. *
  86. * @param {string|Object|undefined} options - An option value to parse.
  87. * @returns {{ArrayExpression: {multiline: boolean, minItems: number}, ArrayPattern: {multiline: boolean, minItems: number}}} Normalized option object.
  88. */
  89. function normalizeOptions(options) {
  90. const value = normalizeOptionValue(options);
  91. return { ArrayExpression: value, ArrayPattern: value };
  92. }
  93. /**
  94. * Reports that there shouldn't be a linebreak after the first token
  95. * @param {ASTNode} node - The node to report in the event of an error.
  96. * @param {Token} token - The token to use for the report.
  97. * @returns {void}
  98. */
  99. function reportNoBeginningLinebreak(node, token) {
  100. context.report({
  101. node,
  102. loc: token.loc,
  103. messageId: "unexpectedOpeningLinebreak",
  104. fix(fixer) {
  105. const nextToken = sourceCode.getTokenAfter(token, { includeComments: true });
  106. if (astUtils.isCommentToken(nextToken)) {
  107. return null;
  108. }
  109. return fixer.removeRange([token.range[1], nextToken.range[0]]);
  110. }
  111. });
  112. }
  113. /**
  114. * Reports that there shouldn't be a linebreak before the last token
  115. * @param {ASTNode} node - The node to report in the event of an error.
  116. * @param {Token} token - The token to use for the report.
  117. * @returns {void}
  118. */
  119. function reportNoEndingLinebreak(node, token) {
  120. context.report({
  121. node,
  122. loc: token.loc,
  123. messageId: "unexpectedClosingLinebreak",
  124. fix(fixer) {
  125. const previousToken = sourceCode.getTokenBefore(token, { includeComments: true });
  126. if (astUtils.isCommentToken(previousToken)) {
  127. return null;
  128. }
  129. return fixer.removeRange([previousToken.range[1], token.range[0]]);
  130. }
  131. });
  132. }
  133. /**
  134. * Reports that there should be a linebreak after the first token
  135. * @param {ASTNode} node - The node to report in the event of an error.
  136. * @param {Token} token - The token to use for the report.
  137. * @returns {void}
  138. */
  139. function reportRequiredBeginningLinebreak(node, token) {
  140. context.report({
  141. node,
  142. loc: token.loc,
  143. messageId: "missingOpeningLinebreak",
  144. fix(fixer) {
  145. return fixer.insertTextAfter(token, "\n");
  146. }
  147. });
  148. }
  149. /**
  150. * Reports that there should be a linebreak before the last token
  151. * @param {ASTNode} node - The node to report in the event of an error.
  152. * @param {Token} token - The token to use for the report.
  153. * @returns {void}
  154. */
  155. function reportRequiredEndingLinebreak(node, token) {
  156. context.report({
  157. node,
  158. loc: token.loc,
  159. messageId: "missingClosingLinebreak",
  160. fix(fixer) {
  161. return fixer.insertTextBefore(token, "\n");
  162. }
  163. });
  164. }
  165. /**
  166. * Reports a given node if it violated this rule.
  167. *
  168. * @param {ASTNode} node - A node to check. This is an ArrayExpression node or an ArrayPattern node.
  169. * @returns {void}
  170. */
  171. function check(node) {
  172. const elements = node.elements;
  173. const normalizedOptions = normalizeOptions(context.options[0]);
  174. const options = normalizedOptions[node.type];
  175. const openBracket = sourceCode.getFirstToken(node);
  176. const closeBracket = sourceCode.getLastToken(node);
  177. const firstIncComment = sourceCode.getTokenAfter(openBracket, { includeComments: true });
  178. const lastIncComment = sourceCode.getTokenBefore(closeBracket, { includeComments: true });
  179. const first = sourceCode.getTokenAfter(openBracket);
  180. const last = sourceCode.getTokenBefore(closeBracket);
  181. const needsLinebreaks = (
  182. elements.length >= options.minItems ||
  183. (
  184. options.multiline &&
  185. elements.length > 0 &&
  186. firstIncComment.loc.start.line !== lastIncComment.loc.end.line
  187. ) ||
  188. (
  189. elements.length === 0 &&
  190. firstIncComment.type === "Block" &&
  191. firstIncComment.loc.start.line !== lastIncComment.loc.end.line &&
  192. firstIncComment === lastIncComment
  193. ) ||
  194. (
  195. options.consistent &&
  196. firstIncComment.loc.start.line !== openBracket.loc.end.line
  197. )
  198. );
  199. /*
  200. * Use tokens or comments to check multiline or not.
  201. * But use only tokens to check whether linebreaks are needed.
  202. * This allows:
  203. * var arr = [ // eslint-disable-line foo
  204. * 'a'
  205. * ]
  206. */
  207. if (needsLinebreaks) {
  208. if (astUtils.isTokenOnSameLine(openBracket, first)) {
  209. reportRequiredBeginningLinebreak(node, openBracket);
  210. }
  211. if (astUtils.isTokenOnSameLine(last, closeBracket)) {
  212. reportRequiredEndingLinebreak(node, closeBracket);
  213. }
  214. } else {
  215. if (!astUtils.isTokenOnSameLine(openBracket, first)) {
  216. reportNoBeginningLinebreak(node, openBracket);
  217. }
  218. if (!astUtils.isTokenOnSameLine(last, closeBracket)) {
  219. reportNoEndingLinebreak(node, closeBracket);
  220. }
  221. }
  222. }
  223. //----------------------------------------------------------------------
  224. // Public
  225. //----------------------------------------------------------------------
  226. return {
  227. ArrayPattern: check,
  228. ArrayExpression: check
  229. };
  230. }
  231. };