line-comment-position.js 4.2 KB

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