implicit-arrow-linebreak.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /**
  2. * @fileoverview enforce the location of arrow function bodies
  3. * @author Sharmila Jesupaul
  4. * @deprecated in ESLint v8.53.0
  5. */
  6. "use strict";
  7. const { isCommentToken, isNotOpeningParenToken } = require("./utils/ast-utils");
  8. //------------------------------------------------------------------------------
  9. // Rule Definition
  10. //------------------------------------------------------------------------------
  11. /** @type {import('../types').Rule.RuleModule} */
  12. module.exports = {
  13. meta: {
  14. deprecated: {
  15. message: "Formatting rules are being moved out of ESLint core.",
  16. url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
  17. deprecatedSince: "8.53.0",
  18. availableUntil: "11.0.0",
  19. replacedBy: [
  20. {
  21. message:
  22. "ESLint Stylistic now maintains deprecated stylistic core rules.",
  23. url: "https://eslint.style/guide/migration",
  24. plugin: {
  25. name: "@stylistic/eslint-plugin",
  26. url: "https://eslint.style",
  27. },
  28. rule: {
  29. name: "implicit-arrow-linebreak",
  30. url: "https://eslint.style/rules/implicit-arrow-linebreak",
  31. },
  32. },
  33. ],
  34. },
  35. type: "layout",
  36. docs: {
  37. description: "Enforce the location of arrow function bodies",
  38. recommended: false,
  39. url: "https://eslint.org/docs/latest/rules/implicit-arrow-linebreak",
  40. },
  41. fixable: "whitespace",
  42. schema: [
  43. {
  44. enum: ["beside", "below"],
  45. },
  46. ],
  47. messages: {
  48. expected: "Expected a linebreak before this expression.",
  49. unexpected: "Expected no linebreak before this expression.",
  50. },
  51. },
  52. create(context) {
  53. const sourceCode = context.sourceCode;
  54. const option = context.options[0] || "beside";
  55. /**
  56. * Validates the location of an arrow function body
  57. * @param {ASTNode} node The arrow function body
  58. * @returns {void}
  59. */
  60. function validateExpression(node) {
  61. if (node.body.type === "BlockStatement") {
  62. return;
  63. }
  64. const arrowToken = sourceCode.getTokenBefore(
  65. node.body,
  66. isNotOpeningParenToken,
  67. );
  68. const firstTokenOfBody = sourceCode.getTokenAfter(arrowToken);
  69. if (
  70. arrowToken.loc.end.line === firstTokenOfBody.loc.start.line &&
  71. option === "below"
  72. ) {
  73. context.report({
  74. node: firstTokenOfBody,
  75. messageId: "expected",
  76. fix: fixer =>
  77. fixer.insertTextBefore(firstTokenOfBody, "\n"),
  78. });
  79. } else if (
  80. arrowToken.loc.end.line !== firstTokenOfBody.loc.start.line &&
  81. option === "beside"
  82. ) {
  83. context.report({
  84. node: firstTokenOfBody,
  85. messageId: "unexpected",
  86. fix(fixer) {
  87. if (
  88. sourceCode.getFirstTokenBetween(
  89. arrowToken,
  90. firstTokenOfBody,
  91. {
  92. includeComments: true,
  93. filter: isCommentToken,
  94. },
  95. )
  96. ) {
  97. return null;
  98. }
  99. return fixer.replaceTextRange(
  100. [arrowToken.range[1], firstTokenOfBody.range[0]],
  101. " ",
  102. );
  103. },
  104. });
  105. }
  106. }
  107. //----------------------------------------------------------------------
  108. // Public
  109. //----------------------------------------------------------------------
  110. return {
  111. ArrowFunctionExpression: node => validateExpression(node),
  112. };
  113. },
  114. };