noMissingSyntax.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. * @typedef {{
  10. * comment: string,
  11. * context: string,
  12. * message: string,
  13. * minimum: import('../iterateJsdoc.js').Integer
  14. * }} ContextObject
  15. */
  16. /**
  17. * @typedef {string|ContextObject} Context
  18. */
  19. /**
  20. * @param {import('../iterateJsdoc.js').StateObject} state
  21. * @returns {void}
  22. */
  23. const setDefaults = state => {
  24. if (!state.selectorMap) {
  25. state.selectorMap = {};
  26. }
  27. };
  28. /**
  29. * @param {import('../iterateJsdoc.js').StateObject} state
  30. * @param {string} selector
  31. * @param {string} comment
  32. * @returns {void}
  33. */
  34. const incrementSelector = (state, selector, comment) => {
  35. if (!state.selectorMap[selector]) {
  36. state.selectorMap[selector] = {};
  37. }
  38. if (!state.selectorMap[selector][comment]) {
  39. state.selectorMap[selector][comment] = 0;
  40. }
  41. state.selectorMap[selector][comment]++;
  42. };
  43. var _default = exports.default = (0, _iterateJsdoc.default)(({
  44. context,
  45. info: {
  46. comment
  47. },
  48. state,
  49. utils
  50. }) => {
  51. if (!context.options[0]) {
  52. // Handle error later
  53. return;
  54. }
  55. /**
  56. * @type {Context[]}
  57. */
  58. const contexts = context.options[0].contexts;
  59. const {
  60. contextStr
  61. } = utils.findContext(contexts, comment);
  62. setDefaults(state);
  63. incrementSelector(state, contextStr, String(comment));
  64. }, {
  65. contextSelected: true,
  66. exit({
  67. context,
  68. settings,
  69. state
  70. }) {
  71. if (!context.options.length && !settings.contexts) {
  72. context.report({
  73. loc: {
  74. end: {
  75. column: 1,
  76. line: 1
  77. },
  78. start: {
  79. column: 1,
  80. line: 1
  81. }
  82. },
  83. message: 'Rule `no-missing-syntax` is missing a `contexts` option.'
  84. });
  85. return;
  86. }
  87. setDefaults(state);
  88. /**
  89. * @type {Context[]}
  90. */
  91. const contexts = (context.options[0] ?? {}).contexts ?? (settings === null || settings === void 0 ? void 0 : settings.contexts);
  92. // Report when MISSING
  93. contexts.some(cntxt => {
  94. const contextStr = typeof cntxt === 'object' ? cntxt.context ?? 'any' : cntxt;
  95. const comment = typeof cntxt === 'string' ? '' : cntxt === null || cntxt === void 0 ? void 0 : cntxt.comment;
  96. const contextKey = contextStr === 'any' ? 'undefined' : contextStr;
  97. if ((!state.selectorMap[contextKey] || !state.selectorMap[contextKey][comment] || state.selectorMap[contextKey][comment] < (
  98. // @ts-expect-error comment would need an object, not string
  99. (cntxt === null || cntxt === void 0 ? void 0 : cntxt.minimum) ?? 1)) && (contextStr !== 'any' || Object.values(state.selectorMap).every(cmmnt => {
  100. return !cmmnt[comment] || cmmnt[comment] < (
  101. // @ts-expect-error comment would need an object, not string
  102. (cntxt === null || cntxt === void 0 ? void 0 : cntxt.minimum) ?? 1);
  103. }))) {
  104. const message = typeof cntxt === 'string' ? 'Syntax is required: {{context}}' : (cntxt === null || cntxt === void 0 ? void 0 : cntxt.message) ?? 'Syntax is required: {{context}}' + (comment ? ' with {{comment}}' : '');
  105. context.report({
  106. data: {
  107. comment,
  108. context: contextStr
  109. },
  110. loc: {
  111. end: {
  112. column: 1,
  113. line: 1
  114. },
  115. start: {
  116. column: 1,
  117. line: 1
  118. }
  119. },
  120. message
  121. });
  122. return true;
  123. }
  124. return false;
  125. });
  126. },
  127. matchContext: true,
  128. meta: {
  129. docs: {
  130. description: 'Reports when certain comment structures are always expected.',
  131. url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-missing-syntax.md#repos-sticky-header'
  132. },
  133. fixable: 'code',
  134. schema: [{
  135. additionalProperties: false,
  136. properties: {
  137. contexts: {
  138. items: {
  139. anyOf: [{
  140. type: 'string'
  141. }, {
  142. additionalProperties: false,
  143. properties: {
  144. comment: {
  145. type: 'string'
  146. },
  147. context: {
  148. type: 'string'
  149. },
  150. message: {
  151. type: 'string'
  152. },
  153. minimum: {
  154. type: 'integer'
  155. }
  156. },
  157. type: 'object'
  158. }]
  159. },
  160. type: 'array'
  161. }
  162. },
  163. type: 'object'
  164. }],
  165. type: 'suggestion'
  166. }
  167. });
  168. module.exports = exports.default;
  169. //# sourceMappingURL=noMissingSyntax.js.map