项目原始demo,不改动
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
Ce dépôt est archivé. Vous pouvez voir les fichiers et le cloner, mais vous ne pouvez pas pousser ni ouvrir de ticket/demande d'ajout.
 
 
 
 

257 lignes
9.4 KiB

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