function-call-argument-newline.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /**
  2. * @fileoverview Rule to enforce line breaks between arguments of a function call
  3. * @author Alexey Gonchar <https://github.com/finico>
  4. * @deprecated in ESLint v8.53.0
  5. */
  6. "use strict";
  7. //------------------------------------------------------------------------------
  8. // Rule Definition
  9. //------------------------------------------------------------------------------
  10. /** @type {import('../types').Rule.RuleModule} */
  11. module.exports = {
  12. meta: {
  13. deprecated: {
  14. message: "Formatting rules are being moved out of ESLint core.",
  15. url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
  16. deprecatedSince: "8.53.0",
  17. availableUntil: "11.0.0",
  18. replacedBy: [
  19. {
  20. message:
  21. "ESLint Stylistic now maintains deprecated stylistic core rules.",
  22. url: "https://eslint.style/guide/migration",
  23. plugin: {
  24. name: "@stylistic/eslint-plugin",
  25. url: "https://eslint.style",
  26. },
  27. rule: {
  28. name: "function-call-argument-newline",
  29. url: "https://eslint.style/rules/function-call-argument-newline",
  30. },
  31. },
  32. ],
  33. },
  34. type: "layout",
  35. docs: {
  36. description:
  37. "Enforce line breaks between arguments of a function call",
  38. recommended: false,
  39. url: "https://eslint.org/docs/latest/rules/function-call-argument-newline",
  40. },
  41. fixable: "whitespace",
  42. schema: [
  43. {
  44. enum: ["always", "never", "consistent"],
  45. },
  46. ],
  47. messages: {
  48. unexpectedLineBreak: "There should be no line break here.",
  49. missingLineBreak:
  50. "There should be a line break after this argument.",
  51. },
  52. },
  53. create(context) {
  54. const sourceCode = context.sourceCode;
  55. const checkers = {
  56. unexpected: {
  57. messageId: "unexpectedLineBreak",
  58. check: (prevToken, currentToken) =>
  59. prevToken.loc.end.line !== currentToken.loc.start.line,
  60. createFix: (token, tokenBefore) => fixer =>
  61. fixer.replaceTextRange(
  62. [tokenBefore.range[1], token.range[0]],
  63. " ",
  64. ),
  65. },
  66. missing: {
  67. messageId: "missingLineBreak",
  68. check: (prevToken, currentToken) =>
  69. prevToken.loc.end.line === currentToken.loc.start.line,
  70. createFix: (token, tokenBefore) => fixer =>
  71. fixer.replaceTextRange(
  72. [tokenBefore.range[1], token.range[0]],
  73. "\n",
  74. ),
  75. },
  76. };
  77. /**
  78. * Check all arguments for line breaks in the CallExpression
  79. * @param {CallExpression} node node to evaluate
  80. * @param {{ messageId: string, check: Function }} checker selected checker
  81. * @returns {void}
  82. * @private
  83. */
  84. function checkArguments(node, checker) {
  85. for (let i = 1; i < node.arguments.length; i++) {
  86. const prevArgToken = sourceCode.getLastToken(
  87. node.arguments[i - 1],
  88. );
  89. const currentArgToken = sourceCode.getFirstToken(
  90. node.arguments[i],
  91. );
  92. if (checker.check(prevArgToken, currentArgToken)) {
  93. const tokenBefore = sourceCode.getTokenBefore(
  94. currentArgToken,
  95. { includeComments: true },
  96. );
  97. const hasLineCommentBefore = tokenBefore.type === "Line";
  98. context.report({
  99. node,
  100. loc: {
  101. start: tokenBefore.loc.end,
  102. end: currentArgToken.loc.start,
  103. },
  104. messageId: checker.messageId,
  105. fix: hasLineCommentBefore
  106. ? null
  107. : checker.createFix(currentArgToken, tokenBefore),
  108. });
  109. }
  110. }
  111. }
  112. /**
  113. * Check if open space is present in a function name
  114. * @param {CallExpression} node node to evaluate
  115. * @returns {void}
  116. * @private
  117. */
  118. function check(node) {
  119. if (node.arguments.length < 2) {
  120. return;
  121. }
  122. const option = context.options[0] || "always";
  123. if (option === "never") {
  124. checkArguments(node, checkers.unexpected);
  125. } else if (option === "always") {
  126. checkArguments(node, checkers.missing);
  127. } else if (option === "consistent") {
  128. const firstArgToken = sourceCode.getLastToken(
  129. node.arguments[0],
  130. );
  131. const secondArgToken = sourceCode.getFirstToken(
  132. node.arguments[1],
  133. );
  134. if (
  135. firstArgToken.loc.end.line === secondArgToken.loc.start.line
  136. ) {
  137. checkArguments(node, checkers.unexpected);
  138. } else {
  139. checkArguments(node, checkers.missing);
  140. }
  141. }
  142. }
  143. return {
  144. CallExpression: check,
  145. NewExpression: check,
  146. };
  147. },
  148. };