requireFileOverview.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.js"));
  7. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  8. const defaultTags = {
  9. file: {
  10. initialCommentsOnly: true,
  11. mustExist: true,
  12. preventDuplicates: true
  13. }
  14. };
  15. /**
  16. * @param {import('../iterateJsdoc.js').StateObject} state
  17. * @returns {void}
  18. */
  19. const setDefaults = state => {
  20. // First iteration
  21. if (!state.globalTags) {
  22. state.globalTags = {};
  23. state.hasDuplicates = {};
  24. state.hasTag = {};
  25. state.hasNonCommentBeforeTag = {};
  26. }
  27. };
  28. var _default = exports.default = (0, _iterateJsdoc.default)(({
  29. jsdocNode,
  30. state,
  31. utils,
  32. context
  33. }) => {
  34. const {
  35. tags = defaultTags
  36. } = context.options[0] || {};
  37. setDefaults(state);
  38. for (const tagName of Object.keys(tags)) {
  39. const targetTagName = /** @type {string} */utils.getPreferredTagName({
  40. tagName
  41. });
  42. const hasTag = Boolean(targetTagName && utils.hasTag(targetTagName));
  43. state.hasTag[tagName] = hasTag || state.hasTag[tagName];
  44. const hasDuplicate = state.hasDuplicates[tagName];
  45. if (hasDuplicate === false) {
  46. // Was marked before, so if a tag now, is a dupe
  47. state.hasDuplicates[tagName] = hasTag;
  48. } else if (!hasDuplicate && hasTag) {
  49. // No dupes set before, but has first tag, so change state
  50. // from `undefined` to `false` so can detect next time
  51. state.hasDuplicates[tagName] = false;
  52. state.hasNonCommentBeforeTag[tagName] = state.hasNonComment && state.hasNonComment < jsdocNode.range[0];
  53. }
  54. }
  55. }, {
  56. exit({
  57. context,
  58. state,
  59. utils
  60. }) {
  61. setDefaults(state);
  62. const {
  63. tags = defaultTags
  64. } = context.options[0] || {};
  65. for (const [tagName, {
  66. mustExist = false,
  67. preventDuplicates = false,
  68. initialCommentsOnly = false
  69. }] of Object.entries(tags)) {
  70. const obj = utils.getPreferredTagNameObject({
  71. tagName
  72. });
  73. if (obj && typeof obj === 'object' && 'blocked' in obj) {
  74. utils.reportSettings(`\`settings.jsdoc.tagNamePreference\` cannot block @${obj.tagName} ` + 'for the `require-file-overview` rule');
  75. } else {
  76. const targetTagName = obj && typeof obj === 'object' && obj.replacement || obj;
  77. if (mustExist && !state.hasTag[tagName]) {
  78. utils.reportSettings(`Missing @${targetTagName}`);
  79. }
  80. if (preventDuplicates && state.hasDuplicates[tagName]) {
  81. utils.reportSettings(`Duplicate @${targetTagName}`);
  82. }
  83. if (initialCommentsOnly && state.hasNonCommentBeforeTag[tagName]) {
  84. utils.reportSettings(`@${targetTagName} should be at the beginning of the file`);
  85. }
  86. }
  87. }
  88. },
  89. iterateAllJsdocs: true,
  90. meta: {
  91. docs: {
  92. description: 'Checks that all files have one `@file`, `@fileoverview`, or `@overview` tag at the beginning of the file.',
  93. url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-file-overview.md#repos-sticky-header'
  94. },
  95. schema: [{
  96. additionalProperties: false,
  97. properties: {
  98. tags: {
  99. patternProperties: {
  100. '.*': {
  101. additionalProperties: false,
  102. properties: {
  103. initialCommentsOnly: {
  104. type: 'boolean'
  105. },
  106. mustExist: {
  107. type: 'boolean'
  108. },
  109. preventDuplicates: {
  110. type: 'boolean'
  111. }
  112. },
  113. type: 'object'
  114. }
  115. },
  116. type: 'object'
  117. }
  118. },
  119. type: 'object'
  120. }],
  121. type: 'suggestion'
  122. },
  123. nonComment({
  124. state,
  125. node
  126. }) {
  127. if (!state.hasNonComment) {
  128. state.hasNonComment = node.range[0];
  129. }
  130. }
  131. });
  132. module.exports = exports.default;
  133. //# sourceMappingURL=requireFileOverview.js.map