dot-location.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /**
  2. * @fileoverview Validates newlines before and after dots
  3. * @author Greg Cochard
  4. * @deprecated in ESLint v8.53.0
  5. */
  6. "use strict";
  7. const astUtils = 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: "dot-location",
  30. url: "https://eslint.style/rules/dot-location",
  31. },
  32. },
  33. ],
  34. },
  35. type: "layout",
  36. docs: {
  37. description: "Enforce consistent newlines before and after dots",
  38. recommended: false,
  39. url: "https://eslint.org/docs/latest/rules/dot-location",
  40. },
  41. schema: [
  42. {
  43. enum: ["object", "property"],
  44. },
  45. ],
  46. fixable: "code",
  47. messages: {
  48. expectedDotAfterObject:
  49. "Expected dot to be on same line as object.",
  50. expectedDotBeforeProperty:
  51. "Expected dot to be on same line as property.",
  52. },
  53. },
  54. create(context) {
  55. const config = context.options[0];
  56. // default to onObject if no preference is passed
  57. const onObject = config === "object" || !config;
  58. const sourceCode = context.sourceCode;
  59. /**
  60. * Reports if the dot between object and property is on the correct location.
  61. * @param {ASTNode} node The `MemberExpression` node.
  62. * @returns {void}
  63. */
  64. function checkDotLocation(node) {
  65. const property = node.property;
  66. const dotToken = sourceCode.getTokenBefore(property);
  67. if (onObject) {
  68. // `obj` expression can be parenthesized, but those paren tokens are not a part of the `obj` node.
  69. const tokenBeforeDot = sourceCode.getTokenBefore(dotToken);
  70. if (!astUtils.isTokenOnSameLine(tokenBeforeDot, dotToken)) {
  71. context.report({
  72. node,
  73. loc: dotToken.loc,
  74. messageId: "expectedDotAfterObject",
  75. *fix(fixer) {
  76. if (
  77. dotToken.value.startsWith(".") &&
  78. astUtils.isDecimalIntegerNumericToken(
  79. tokenBeforeDot,
  80. )
  81. ) {
  82. yield fixer.insertTextAfter(
  83. tokenBeforeDot,
  84. ` ${dotToken.value}`,
  85. );
  86. } else {
  87. yield fixer.insertTextAfter(
  88. tokenBeforeDot,
  89. dotToken.value,
  90. );
  91. }
  92. yield fixer.remove(dotToken);
  93. },
  94. });
  95. }
  96. } else if (!astUtils.isTokenOnSameLine(dotToken, property)) {
  97. context.report({
  98. node,
  99. loc: dotToken.loc,
  100. messageId: "expectedDotBeforeProperty",
  101. *fix(fixer) {
  102. yield fixer.remove(dotToken);
  103. yield fixer.insertTextBefore(property, dotToken.value);
  104. },
  105. });
  106. }
  107. }
  108. /**
  109. * Checks the spacing of the dot within a member expression.
  110. * @param {ASTNode} node The node to check.
  111. * @returns {void}
  112. */
  113. function checkNode(node) {
  114. if (!node.computed) {
  115. checkDotLocation(node);
  116. }
  117. }
  118. return {
  119. MemberExpression: checkNode,
  120. };
  121. },
  122. };