requireDescription.js 3.8 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. /**
  9. * @param {string} description
  10. * @returns {import('../iterateJsdoc.js').Integer}
  11. */
  12. const checkDescription = description => {
  13. return description.trim().split('\n').filter(Boolean).length;
  14. };
  15. var _default = exports.default = (0, _iterateJsdoc.default)(({
  16. jsdoc,
  17. report,
  18. utils,
  19. context
  20. }) => {
  21. if (utils.avoidDocs()) {
  22. return;
  23. }
  24. const {
  25. descriptionStyle = 'body'
  26. } = context.options[0] || {};
  27. let targetTagName = utils.getPreferredTagName({
  28. // We skip reporting except when `@description` is essential to the rule,
  29. // so user can block the tag and still meaningfully use this rule
  30. // even if the tag is present (and `check-tag-names` is the one to
  31. // normally report the fact that it is blocked but present)
  32. skipReportingBlockedTag: descriptionStyle !== 'tag',
  33. tagName: 'description'
  34. });
  35. if (!targetTagName) {
  36. return;
  37. }
  38. const isBlocked = typeof targetTagName === 'object' && 'blocked' in targetTagName && targetTagName.blocked;
  39. if (isBlocked) {
  40. targetTagName = /** @type {{blocked: true; tagName: string;}} */targetTagName.tagName;
  41. }
  42. if (descriptionStyle !== 'tag') {
  43. const {
  44. description
  45. } = utils.getDescription();
  46. if (checkDescription(description || '')) {
  47. return;
  48. }
  49. if (descriptionStyle === 'body') {
  50. const descTags = utils.getPresentTags(['desc', 'description']);
  51. if (descTags.length) {
  52. const [{
  53. tag: tagName
  54. }] = descTags;
  55. report(`Remove the @${tagName} tag to leave a plain block description or add additional description text above the @${tagName} line.`);
  56. } else {
  57. report('Missing JSDoc block description.');
  58. }
  59. return;
  60. }
  61. }
  62. const functionExamples = isBlocked ? [] : jsdoc.tags.filter(({
  63. tag
  64. }) => {
  65. return tag === targetTagName;
  66. });
  67. if (!functionExamples.length) {
  68. report(descriptionStyle === 'any' ? `Missing JSDoc block description or @${targetTagName} declaration.` : `Missing JSDoc @${targetTagName} declaration.`);
  69. return;
  70. }
  71. for (const example of functionExamples) {
  72. if (!checkDescription(`${example.name} ${utils.getTagDescription(example)}`)) {
  73. report(`Missing JSDoc @${targetTagName} description.`, null, example);
  74. }
  75. }
  76. }, {
  77. contextDefaults: true,
  78. meta: {
  79. docs: {
  80. description: 'Requires that all functions have a description.',
  81. url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-description.md#repos-sticky-header'
  82. },
  83. schema: [{
  84. additionalProperties: false,
  85. properties: {
  86. checkConstructors: {
  87. default: true,
  88. type: 'boolean'
  89. },
  90. checkGetters: {
  91. default: true,
  92. type: 'boolean'
  93. },
  94. checkSetters: {
  95. default: true,
  96. type: 'boolean'
  97. },
  98. contexts: {
  99. items: {
  100. anyOf: [{
  101. type: 'string'
  102. }, {
  103. additionalProperties: false,
  104. properties: {
  105. comment: {
  106. type: 'string'
  107. },
  108. context: {
  109. type: 'string'
  110. }
  111. },
  112. type: 'object'
  113. }]
  114. },
  115. type: 'array'
  116. },
  117. descriptionStyle: {
  118. enum: ['body', 'tag', 'any'],
  119. type: 'string'
  120. },
  121. exemptedBy: {
  122. items: {
  123. type: 'string'
  124. },
  125. type: 'array'
  126. }
  127. },
  128. type: 'object'
  129. }],
  130. type: 'suggestion'
  131. }
  132. });
  133. module.exports = exports.default;
  134. //# sourceMappingURL=requireDescription.js.map