line-comment-position.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /**
  2. * @fileoverview Rule to enforce the position of line comments
  3. * @author Alberto Rodríguez
  4. */
  5. "use strict";
  6. const astUtils = require("./utils/ast-utils");
  7. //------------------------------------------------------------------------------
  8. // Rule Definition
  9. //------------------------------------------------------------------------------
  10. /** @type {import('../shared/types').Rule} */
  11. module.exports = {
  12. meta: {
  13. type: "layout",
  14. docs: {
  15. description: "Enforce position of line comments",
  16. recommended: false,
  17. url: "https://eslint.org/docs/rules/line-comment-position"
  18. },
  19. schema: [
  20. {
  21. oneOf: [
  22. {
  23. enum: ["above", "beside"]
  24. },
  25. {
  26. type: "object",
  27. properties: {
  28. position: {
  29. enum: ["above", "beside"]
  30. },
  31. ignorePattern: {
  32. type: "string"
  33. },
  34. applyDefaultPatterns: {
  35. type: "boolean"
  36. },
  37. applyDefaultIgnorePatterns: {
  38. type: "boolean"
  39. }
  40. },
  41. additionalProperties: false
  42. }
  43. ]
  44. }
  45. ],
  46. messages: {
  47. above: "Expected comment to be above code.",
  48. beside: "Expected comment to be beside code."
  49. }
  50. },
  51. create(context) {
  52. const options = context.options[0];
  53. let above,
  54. ignorePattern,
  55. applyDefaultIgnorePatterns = true;
  56. if (!options || typeof options === "string") {
  57. above = !options || options === "above";
  58. } else {
  59. above = !options.position || options.position === "above";
  60. ignorePattern = options.ignorePattern;
  61. if (Object.prototype.hasOwnProperty.call(options, "applyDefaultIgnorePatterns")) {
  62. applyDefaultIgnorePatterns = options.applyDefaultIgnorePatterns;
  63. } else {
  64. applyDefaultIgnorePatterns = options.applyDefaultPatterns !== false;
  65. }
  66. }
  67. const defaultIgnoreRegExp = astUtils.COMMENTS_IGNORE_PATTERN;
  68. const fallThroughRegExp = /^\s*falls?\s?through/u;
  69. const customIgnoreRegExp = new RegExp(ignorePattern, "u");
  70. const sourceCode = context.getSourceCode();
  71. //--------------------------------------------------------------------------
  72. // Public
  73. //--------------------------------------------------------------------------
  74. return {
  75. Program() {
  76. const comments = sourceCode.getAllComments();
  77. comments.filter(token => token.type === "Line").forEach(node => {
  78. if (applyDefaultIgnorePatterns && (defaultIgnoreRegExp.test(node.value) || fallThroughRegExp.test(node.value))) {
  79. return;
  80. }
  81. if (ignorePattern && customIgnoreRegExp.test(node.value)) {
  82. return;
  83. }
  84. const previous = sourceCode.getTokenBefore(node, { includeComments: true });
  85. const isOnSameLine = previous && previous.loc.end.line === node.loc.start.line;
  86. if (above) {
  87. if (isOnSameLine) {
  88. context.report({
  89. node,
  90. messageId: "above"
  91. });
  92. }
  93. } else {
  94. if (!isOnSameLine) {
  95. context.report({
  96. node,
  97. messageId: "beside"
  98. });
  99. }
  100. }
  101. });
  102. }
  103. };
  104. }
  105. };