eslint-plugin-jsdoc 56.1.2 → 57.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +10 -11
  2. package/dist/cjs/index-cjs.d.ts +10 -0
  3. package/dist/cjs/iterateJsdoc.d.ts +21 -5
  4. package/dist/exportParser.cjs +0 -6
  5. package/dist/exportParser.cjs.map +1 -1
  6. package/dist/index-cjs.cjs +108 -3
  7. package/dist/index-cjs.cjs.map +1 -1
  8. package/dist/index-cjs.d.ts +10 -0
  9. package/dist/index-esm.cjs +36 -10
  10. package/dist/index-esm.cjs.map +1 -1
  11. package/dist/index-esm.d.ts +29 -3
  12. package/dist/index.cjs +142 -10
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.ts +39 -3
  15. package/dist/iterateJsdoc.cjs +14 -8
  16. package/dist/iterateJsdoc.cjs.map +1 -1
  17. package/dist/iterateJsdoc.d.ts +21 -5
  18. package/dist/jsdocUtils.cjs +0 -3
  19. package/dist/jsdocUtils.cjs.map +1 -1
  20. package/dist/rules/checkParamNames.cjs +1 -1
  21. package/dist/rules/checkParamNames.cjs.map +1 -1
  22. package/dist/rules/checkPropertyNames.cjs +1 -1
  23. package/dist/rules/checkPropertyNames.cjs.map +1 -1
  24. package/dist/rules/informativeDocs.cjs +0 -3
  25. package/dist/rules/informativeDocs.cjs.map +1 -1
  26. package/dist/rules/matchName.cjs +0 -1
  27. package/dist/rules/matchName.cjs.map +1 -1
  28. package/dist/rules/noMultiAsterisks.cjs +0 -2
  29. package/dist/rules/noMultiAsterisks.cjs.map +1 -1
  30. package/dist/rules/requireReturnsCheck.cjs +0 -2
  31. package/dist/rules/requireReturnsCheck.cjs.map +1 -1
  32. package/dist/rules/sortTags.cjs +0 -2
  33. package/dist/rules/sortTags.cjs.map +1 -1
  34. package/dist/rules/tagLines.cjs +0 -2
  35. package/dist/rules/tagLines.cjs.map +1 -1
  36. package/package.json +2 -1
  37. package/src/exportParser.js +0 -6
  38. package/src/index-cjs.js +125 -0
  39. package/src/index-esm.js +43 -13
  40. package/src/index.js +165 -12
  41. package/src/iterateJsdoc.js +17 -8
  42. package/src/jsdocUtils.js +0 -3
  43. package/src/rules/checkParamNames.js +1 -1
  44. package/src/rules/checkPropertyNames.js +1 -1
  45. package/src/rules/informativeDocs.js +0 -3
  46. package/src/rules/matchName.js +0 -1
  47. package/src/rules/noMultiAsterisks.js +0 -1
  48. package/src/rules/requireReturnsCheck.js +0 -1
  49. package/src/rules/sortTags.js +0 -2
  50. package/src/rules/tagLines.js +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"tagLines.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","context","jsdoc","utils","alwaysNever","applyToEndTag","count","endLines","startLines","tags","options","some","tg","tagIdx","lastTag","lastEmpty","reportIndex","emptyLinesCount","idx","tokens","description","end","name","tag","type","source","entries","includes","slice","lines","empty","length","lineDiff","fixer","removeTag","tagSourceOffset","reportJSDoc","line","number","addLines","currentTag","tagSourceIdx","splice","push","currentTg","tagCount","defaultAlways","overrideAlways","fixCount","lastDescriptionLine","getDescription","test","trailingLines","match","trailingDiff","setBlockDescription","info","seedTokens","descLines","map","desc","postDelimiter","trim","Array","from","iterateAllJsdocs","meta","docs","url","fixable","schema","enum","additionalProperties","properties","anyOf","patternProperties","module"],"sources":["../../src/rules/tagLines.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n context,\n jsdoc,\n utils,\n}) => {\n const [\n alwaysNever = 'never',\n {\n applyToEndTag = true,\n count = 1,\n endLines = 0,\n startLines = 0,\n tags = {},\n } = {},\n ] = context.options;\n\n // eslint-disable-next-line complexity -- Temporary\n jsdoc.tags.some((tg, tagIdx) => {\n let lastTag;\n\n /**\n * @type {null|import('../iterateJsdoc.js').Integer}\n */\n let lastEmpty = null;\n\n /**\n * @type {null|import('../iterateJsdoc.js').Integer}\n */\n let reportIndex = null;\n let emptyLinesCount = 0;\n for (const [\n idx,\n {\n tokens: {\n description,\n end,\n name,\n tag,\n type,\n },\n },\n ] of tg.source.entries()) {\n // May be text after a line break within a tag description\n if (description) {\n reportIndex = null;\n }\n\n if (lastTag && [\n 'always', 'any',\n ].includes(tags[lastTag.slice(1)]?.lines)) {\n continue;\n }\n\n const empty = !tag && !name && !type && !description;\n if (\n empty && !end &&\n (alwaysNever === 'never' ||\n lastTag && tags[lastTag.slice(1)]?.lines === 'never'\n )\n ) {\n reportIndex = idx;\n\n continue;\n }\n\n if (!end) {\n if (empty) {\n emptyLinesCount++;\n } else {\n emptyLinesCount = 0;\n }\n\n lastEmpty = empty ? idx : null;\n }\n\n lastTag = tag;\n }\n\n if (\n typeof endLines === 'number' &&\n lastEmpty !== null && tagIdx === jsdoc.tags.length - 1\n ) {\n const lineDiff = endLines - emptyLinesCount;\n\n if (lineDiff < 0) {\n const fixer = () => {\n utils.removeTag(tagIdx, {\n tagSourceOffset: /** @type {import('../iterateJsdoc.js').Integer} */ (\n lastEmpty\n ) + lineDiff + 1,\n });\n };\n\n utils.reportJSDoc(\n `Expected ${endLines} trailing lines`,\n {\n line: tg.source[lastEmpty].number + lineDiff + 1,\n },\n fixer,\n );\n } else if (lineDiff > 0) {\n const fixer = () => {\n utils.addLines(\n tagIdx,\n /** @type {import('../iterateJsdoc.js').Integer} */ (lastEmpty),\n endLines - emptyLinesCount,\n );\n };\n\n utils.reportJSDoc(\n `Expected ${endLines} trailing lines`,\n {\n line: tg.source[lastEmpty].number,\n },\n fixer,\n );\n }\n\n return true;\n }\n\n if (reportIndex !== null) {\n const fixer = () => {\n utils.removeTag(tagIdx, {\n tagSourceOffset: /** @type {import('../iterateJsdoc.js').Integer} */ (\n reportIndex\n ),\n });\n };\n\n utils.reportJSDoc(\n 'Expected no lines between tags',\n {\n line: tg.source[0].number + 1,\n },\n fixer,\n );\n\n return true;\n }\n\n return false;\n });\n\n (applyToEndTag ? jsdoc.tags : jsdoc.tags.slice(0, -1)).some((tg, tagIdx) => {\n /**\n * @type {{\n * idx: import('../iterateJsdoc.js').Integer,\n * number: import('../iterateJsdoc.js').Integer\n * }[]}\n */\n const lines = [];\n\n let currentTag;\n let tagSourceIdx = 0;\n for (const [\n idx,\n {\n number,\n tokens: {\n description,\n end,\n name,\n tag,\n type,\n },\n },\n ] of tg.source.entries()) {\n if (description) {\n lines.splice(0);\n tagSourceIdx = idx;\n }\n\n if (tag) {\n currentTag = tag;\n }\n\n if (!tag && !name && !type && !description && !end) {\n lines.push({\n idx,\n number,\n });\n }\n }\n\n const currentTg = currentTag && tags[currentTag.slice(1)];\n const tagCount = currentTg?.count;\n\n const defaultAlways = alwaysNever === 'always' && currentTg?.lines !== 'never' &&\n currentTg?.lines !== 'any' && lines.length < count;\n\n let overrideAlways;\n let fixCount = count;\n if (!defaultAlways) {\n fixCount = typeof tagCount === 'number' ? tagCount : count;\n overrideAlways = currentTg?.lines === 'always' &&\n lines.length < fixCount;\n }\n\n if (defaultAlways || overrideAlways) {\n const fixer = () => {\n utils.addLines(tagIdx, lines[lines.length - 1]?.idx || tagSourceIdx + 1, fixCount - lines.length);\n };\n\n const line = lines[lines.length - 1]?.number || tg.source[tagSourceIdx].number;\n utils.reportJSDoc(\n `Expected ${fixCount} line${fixCount === 1 ? '' : 's'} between tags but found ${lines.length}`,\n {\n line,\n },\n fixer,\n );\n\n return true;\n }\n\n return false;\n });\n\n if (typeof startLines === 'number') {\n if (!jsdoc.tags.length) {\n return;\n }\n\n const {\n description,\n lastDescriptionLine,\n } = utils.getDescription();\n if (!(/\\S/v).test(description)) {\n return;\n }\n\n const trailingLines = description.match(/\\n+$/v)?.[0]?.length;\n const trailingDiff = (trailingLines ?? 0) - startLines;\n if (trailingDiff > 0) {\n utils.reportJSDoc(\n `Expected only ${startLines} line after block description`,\n {\n line: lastDescriptionLine - trailingDiff,\n },\n () => {\n utils.setBlockDescription((info, seedTokens, descLines) => {\n return descLines.slice(0, -trailingDiff).map((desc) => {\n return {\n number: 0,\n source: '',\n tokens: seedTokens({\n ...info,\n description: desc,\n postDelimiter: desc.trim() ? info.postDelimiter : '',\n }),\n };\n });\n });\n },\n );\n } else if (trailingDiff < 0) {\n utils.reportJSDoc(\n `Expected ${startLines} lines after block description`,\n {\n line: lastDescriptionLine,\n },\n () => {\n utils.setBlockDescription((info, seedTokens, descLines) => {\n return [\n ...descLines,\n ...Array.from({\n length: -trailingDiff,\n }, () => {\n return '';\n }),\n ].map((desc) => {\n return {\n number: 0,\n source: '',\n tokens: seedTokens({\n ...info,\n description: desc,\n postDelimiter: desc.trim() ? info.postDelimiter : '',\n }),\n };\n });\n });\n },\n );\n }\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Enforces lines (or no lines) between tags.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/tag-lines.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n enum: [\n 'always', 'any', 'never',\n ],\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n applyToEndTag: {\n type: 'boolean',\n },\n count: {\n type: 'integer',\n },\n endLines: {\n anyOf: [\n {\n type: 'integer',\n },\n {\n type: 'null',\n },\n ],\n },\n startLines: {\n anyOf: [\n {\n type: 'integer',\n },\n {\n type: 'null',\n },\n ],\n },\n tags: {\n patternProperties: {\n '.*': {\n additionalProperties: false,\n properties: {\n count: {\n type: 'integer',\n },\n lines: {\n enum: [\n 'always', 'never', 'any',\n ],\n type: 'string',\n },\n },\n },\n },\n type: 'object',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"tagLines.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","context","jsdoc","utils","alwaysNever","applyToEndTag","count","endLines","startLines","tags","options","some","tg","tagIdx","lastTag","lastEmpty","reportIndex","emptyLinesCount","idx","tokens","description","end","name","tag","type","source","entries","includes","slice","lines","empty","length","lineDiff","fixer","removeTag","tagSourceOffset","reportJSDoc","line","number","addLines","currentTag","tagSourceIdx","splice","push","currentTg","tagCount","defaultAlways","overrideAlways","fixCount","lastDescriptionLine","getDescription","test","trailingLines","match","trailingDiff","setBlockDescription","info","seedTokens","descLines","map","desc","postDelimiter","trim","Array","from","iterateAllJsdocs","meta","docs","url","fixable","schema","enum","additionalProperties","properties","anyOf","patternProperties","module"],"sources":["../../src/rules/tagLines.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n context,\n jsdoc,\n utils,\n}) => {\n const [\n alwaysNever = 'never',\n {\n applyToEndTag = true,\n count = 1,\n endLines = 0,\n startLines = 0,\n tags = {},\n } = {},\n ] = context.options;\n\n jsdoc.tags.some((tg, tagIdx) => {\n let lastTag;\n\n /**\n * @type {null|import('../iterateJsdoc.js').Integer}\n */\n let lastEmpty = null;\n\n /**\n * @type {null|import('../iterateJsdoc.js').Integer}\n */\n let reportIndex = null;\n let emptyLinesCount = 0;\n for (const [\n idx,\n {\n tokens: {\n description,\n end,\n name,\n tag,\n type,\n },\n },\n ] of tg.source.entries()) {\n // May be text after a line break within a tag description\n if (description) {\n reportIndex = null;\n }\n\n if (lastTag && [\n 'always', 'any',\n ].includes(tags[lastTag.slice(1)]?.lines)) {\n continue;\n }\n\n const empty = !tag && !name && !type && !description;\n if (\n empty && !end &&\n (alwaysNever === 'never' ||\n lastTag && tags[lastTag.slice(1)]?.lines === 'never'\n )\n ) {\n reportIndex = idx;\n\n continue;\n }\n\n if (!end) {\n if (empty) {\n emptyLinesCount++;\n } else {\n emptyLinesCount = 0;\n }\n\n lastEmpty = empty ? idx : null;\n }\n\n lastTag = tag;\n }\n\n if (\n typeof endLines === 'number' &&\n lastEmpty !== null && tagIdx === jsdoc.tags.length - 1\n ) {\n const lineDiff = endLines - emptyLinesCount;\n\n if (lineDiff < 0) {\n const fixer = () => {\n utils.removeTag(tagIdx, {\n tagSourceOffset: /** @type {import('../iterateJsdoc.js').Integer} */ (\n lastEmpty\n ) + lineDiff + 1,\n });\n };\n\n utils.reportJSDoc(\n `Expected ${endLines} trailing lines`,\n {\n line: tg.source[lastEmpty].number + lineDiff + 1,\n },\n fixer,\n );\n } else if (lineDiff > 0) {\n const fixer = () => {\n utils.addLines(\n tagIdx,\n /** @type {import('../iterateJsdoc.js').Integer} */ (lastEmpty),\n endLines - emptyLinesCount,\n );\n };\n\n utils.reportJSDoc(\n `Expected ${endLines} trailing lines`,\n {\n line: tg.source[lastEmpty].number,\n },\n fixer,\n );\n }\n\n return true;\n }\n\n if (reportIndex !== null) {\n const fixer = () => {\n utils.removeTag(tagIdx, {\n tagSourceOffset: /** @type {import('../iterateJsdoc.js').Integer} */ (\n reportIndex\n ),\n });\n };\n\n utils.reportJSDoc(\n 'Expected no lines between tags',\n {\n line: tg.source[0].number + 1,\n },\n fixer,\n );\n\n return true;\n }\n\n return false;\n });\n\n (applyToEndTag ? jsdoc.tags : jsdoc.tags.slice(0, -1)).some((tg, tagIdx) => {\n /**\n * @type {{\n * idx: import('../iterateJsdoc.js').Integer,\n * number: import('../iterateJsdoc.js').Integer\n * }[]}\n */\n const lines = [];\n\n let currentTag;\n let tagSourceIdx = 0;\n for (const [\n idx,\n {\n number,\n tokens: {\n description,\n end,\n name,\n tag,\n type,\n },\n },\n ] of tg.source.entries()) {\n if (description) {\n lines.splice(0);\n tagSourceIdx = idx;\n }\n\n if (tag) {\n currentTag = tag;\n }\n\n if (!tag && !name && !type && !description && !end) {\n lines.push({\n idx,\n number,\n });\n }\n }\n\n const currentTg = currentTag && tags[currentTag.slice(1)];\n const tagCount = currentTg?.count;\n\n const defaultAlways = alwaysNever === 'always' && currentTg?.lines !== 'never' &&\n currentTg?.lines !== 'any' && lines.length < count;\n\n let overrideAlways;\n let fixCount = count;\n if (!defaultAlways) {\n fixCount = typeof tagCount === 'number' ? tagCount : count;\n overrideAlways = currentTg?.lines === 'always' &&\n lines.length < fixCount;\n }\n\n if (defaultAlways || overrideAlways) {\n const fixer = () => {\n utils.addLines(tagIdx, lines[lines.length - 1]?.idx || tagSourceIdx + 1, fixCount - lines.length);\n };\n\n const line = lines[lines.length - 1]?.number || tg.source[tagSourceIdx].number;\n utils.reportJSDoc(\n `Expected ${fixCount} line${fixCount === 1 ? '' : 's'} between tags but found ${lines.length}`,\n {\n line,\n },\n fixer,\n );\n\n return true;\n }\n\n return false;\n });\n\n if (typeof startLines === 'number') {\n if (!jsdoc.tags.length) {\n return;\n }\n\n const {\n description,\n lastDescriptionLine,\n } = utils.getDescription();\n if (!(/\\S/v).test(description)) {\n return;\n }\n\n const trailingLines = description.match(/\\n+$/v)?.[0]?.length;\n const trailingDiff = (trailingLines ?? 0) - startLines;\n if (trailingDiff > 0) {\n utils.reportJSDoc(\n `Expected only ${startLines} line after block description`,\n {\n line: lastDescriptionLine - trailingDiff,\n },\n () => {\n utils.setBlockDescription((info, seedTokens, descLines) => {\n return descLines.slice(0, -trailingDiff).map((desc) => {\n return {\n number: 0,\n source: '',\n tokens: seedTokens({\n ...info,\n description: desc,\n postDelimiter: desc.trim() ? info.postDelimiter : '',\n }),\n };\n });\n });\n },\n );\n } else if (trailingDiff < 0) {\n utils.reportJSDoc(\n `Expected ${startLines} lines after block description`,\n {\n line: lastDescriptionLine,\n },\n () => {\n utils.setBlockDescription((info, seedTokens, descLines) => {\n return [\n ...descLines,\n ...Array.from({\n length: -trailingDiff,\n }, () => {\n return '';\n }),\n ].map((desc) => {\n return {\n number: 0,\n source: '',\n tokens: seedTokens({\n ...info,\n description: desc,\n postDelimiter: desc.trim() ? info.postDelimiter : '',\n }),\n };\n });\n });\n },\n );\n }\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Enforces lines (or no lines) between tags.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/tag-lines.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n enum: [\n 'always', 'any', 'never',\n ],\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n applyToEndTag: {\n type: 'boolean',\n },\n count: {\n type: 'integer',\n },\n endLines: {\n anyOf: [\n {\n type: 'integer',\n },\n {\n type: 'null',\n },\n ],\n },\n startLines: {\n anyOf: [\n {\n type: 'integer',\n },\n {\n type: 'null',\n },\n ],\n },\n tags: {\n patternProperties: {\n '.*': {\n additionalProperties: false,\n properties: {\n count: {\n type: 'integer',\n },\n lines: {\n enum: [\n 'always', 'never', 'any',\n ],\n type: 'string',\n },\n },\n },\n },\n type: 'object',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -28,6 +28,7 @@
28
28
  "@babel/preset-env": "^7.28.3",
29
29
  "@es-joy/escodegen": "^3.5.1",
30
30
  "@es-joy/jsdoc-eslint-parser": "^0.23.0",
31
+ "@eslint/core": "^0.15.2",
31
32
  "@hkdobrev/run-if-changed": "^0.6.3",
32
33
  "@semantic-release/commit-analyzer": "^13.0.1",
33
34
  "@semantic-release/github": "^11.0.5",
@@ -171,5 +172,5 @@
171
172
  "test-cov": "TIMING=1 c8 --reporter text pnpm run test-no-cov",
172
173
  "test-index": "pnpm run test-no-cov test/rules/index.js"
173
174
  },
174
- "version": "56.1.2"
175
+ "version": "57.0.1"
175
176
  }
@@ -103,8 +103,6 @@ const getIdentifier = function (node, globals, scope, opts) {
103
103
  /** @type {CreateSymbol} */
104
104
  let createSymbol; // eslint-disable-line prefer-const
105
105
 
106
- /* eslint-disable complexity -- Temporary */
107
-
108
106
  /**
109
107
  * @typedef {{
110
108
  * simpleIdentifier?: boolean
@@ -120,7 +118,6 @@ let createSymbol; // eslint-disable-line prefer-const
120
118
  * @returns {CreatedNode|null}
121
119
  */
122
120
  const getSymbol = function (node, globals, scope, opt) {
123
- /* eslint-enable complexity -- Temporary */
124
121
  const opts = opt || {};
125
122
  /* c8 ignore next */
126
123
  switch (node.type) {
@@ -478,8 +475,6 @@ const initVariables = function (node, globals, opts) {
478
475
  }
479
476
  };
480
477
 
481
- /* eslint-disable complexity -- Temporary */
482
-
483
478
  /**
484
479
  * Populates variable maps using AST
485
480
  * @param {import('eslint').Rule.Node|import('@typescript-eslint/types').TSESTree.Node} node
@@ -489,7 +484,6 @@ const initVariables = function (node, globals, opts) {
489
484
  * @returns {boolean}
490
485
  */
491
486
  const mapVariables = function (node, globals, opt, isExport) {
492
- /* eslint-enable complexity -- Temporary */
493
487
  /* c8 ignore next */
494
488
  const opts = opt || {};
495
489
  /* c8 ignore next */
package/src/index-cjs.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  getJsdocProcessorPlugin,
3
3
  } from './getJsdocProcessorPlugin.js';
4
+ import iterateJsdoc from './iterateJsdoc.js';
4
5
  import checkAccess from './rules/checkAccess.js';
5
6
  import checkAlignment from './rules/checkAlignment.js';
6
7
  import checkExamples from './rules/checkExamples.js';
@@ -60,6 +61,91 @@ import textEscaping from './rules/textEscaping.js';
60
61
  import typeFormatting from './rules/typeFormatting.js';
61
62
  import validTypes from './rules/validTypes.js';
62
63
 
64
+ /**
65
+ * @param {{
66
+ * contexts: (string|{
67
+ * comment: string,
68
+ * context: string,
69
+ * message: string
70
+ * })[],
71
+ * description?: string,
72
+ * contextName?: string
73
+ * url?: string,
74
+ * }} cfg
75
+ * @returns {import('@eslint/core').RuleDefinition<
76
+ * import('@eslint/core').RuleDefinitionTypeOptions
77
+ * >}
78
+ */
79
+ export const buildForbidRuleDefinition = ({
80
+ contextName,
81
+ contexts,
82
+ description,
83
+ url,
84
+ }) => {
85
+ return iterateJsdoc(({
86
+ // context,
87
+ info: {
88
+ comment,
89
+ },
90
+ report,
91
+ utils,
92
+ }) => {
93
+ const {
94
+ contextStr,
95
+ foundContext,
96
+ } = utils.findContext(contexts, comment);
97
+
98
+ // We are not on the *particular* matching context/comment, so don't assume
99
+ // we need reporting
100
+ if (!foundContext) {
101
+ return;
102
+ }
103
+
104
+ const message = /** @type {import('./iterateJsdoc.js').ContextObject} */ (
105
+ foundContext
106
+ )?.message ??
107
+ 'Syntax is restricted: {{context}}' +
108
+ (comment ? ' with {{comment}}' : '');
109
+
110
+ report(message, null, null, comment ? {
111
+ comment,
112
+ context: contextStr,
113
+ } : {
114
+ context: contextStr,
115
+ });
116
+ }, {
117
+ contextSelected: true,
118
+ meta: {
119
+ docs: {
120
+ description: description ?? contextName ?? 'Reports when certain comment structures are present.',
121
+ url: url ?? 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-restricted-syntax.md#repos-sticky-header',
122
+ },
123
+ fixable: 'code',
124
+ schema: [],
125
+ type: 'suggestion',
126
+ },
127
+ modifyContext: (context) => {
128
+ // Reproduce context object with our own `contexts`
129
+ const propertyDescriptors = Object.getOwnPropertyDescriptors(context);
130
+ return Object.create(
131
+ Object.getPrototypeOf(context),
132
+ {
133
+ ...propertyDescriptors,
134
+ options: {
135
+ ...propertyDescriptors.options,
136
+ value: [
137
+ {
138
+ contexts,
139
+ },
140
+ ],
141
+ },
142
+ },
143
+ );
144
+ },
145
+ nonGlobalSettings: true,
146
+ });
147
+ };
148
+
63
149
  /* eslint-disable jsdoc/valid-types -- Bug */
64
150
  /**
65
151
  * @typedef {"recommended" | "stylistic" | "contents" | "logical" | "requirements"} ConfigGroups
@@ -111,6 +197,17 @@ index.rules = {
111
197
  'require-file-overview': requireFileOverview,
112
198
  'require-hyphen-before-param-description': requireHyphenBeforeParamDescription,
113
199
  'require-jsdoc': requireJsdoc,
200
+ 'require-next-type': buildForbidRuleDefinition({
201
+ contexts: [
202
+ {
203
+ comment: 'JsdocBlock:has(JsdocTag[tag=next]:not([parsedType.type]))',
204
+ context: 'any',
205
+ message: '@next should have a type',
206
+ },
207
+ ],
208
+ description: 'Requires a type for @next tags',
209
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-next-type.md#repos-sticky-header',
210
+ }),
114
211
  'require-param': requireParam,
115
212
  'require-param-description': requireParamDescription,
116
213
  'require-param-name': requireParamName,
@@ -125,8 +222,30 @@ index.rules = {
125
222
  'require-returns-type': requireReturnsType,
126
223
  'require-template': requireTemplate,
127
224
  'require-throws': requireThrows,
225
+ 'require-throws-type': buildForbidRuleDefinition({
226
+ contexts: [
227
+ {
228
+ comment: 'JsdocBlock:has(JsdocTag[tag=throws]:not([parsedType.type]))',
229
+ context: 'any',
230
+ message: '@throws should have a type',
231
+ },
232
+ ],
233
+ description: 'Requires a type for @throws tags',
234
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-throws-type.md#repos-sticky-header',
235
+ }),
128
236
  'require-yields': requireYields,
129
237
  'require-yields-check': requireYieldsCheck,
238
+ 'require-yields-type': buildForbidRuleDefinition({
239
+ contexts: [
240
+ {
241
+ comment: 'JsdocBlock:has(JsdocTag[tag=yields]:not([parsedType.type]))',
242
+ context: 'any',
243
+ message: '@yields should have a type',
244
+ },
245
+ ],
246
+ description: 'Requires a type for @yields tags',
247
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-yields-type.md#repos-sticky-header',
248
+ }),
130
249
  'sort-tags': sortTags,
131
250
  'tag-lines': tagLines,
132
251
  'text-escaping': textEscaping,
@@ -189,6 +308,7 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
189
308
  'jsdoc/require-file-overview': 'off',
190
309
  'jsdoc/require-hyphen-before-param-description': 'off',
191
310
  'jsdoc/require-jsdoc': warnOrError,
311
+ 'jsdoc/require-next-type': warnOrError,
192
312
  'jsdoc/require-param': warnOrError,
193
313
  'jsdoc/require-param-description': warnOrError,
194
314
  'jsdoc/require-param-name': warnOrError,
@@ -203,8 +323,10 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
203
323
  'jsdoc/require-returns-type': warnOrError,
204
324
  'jsdoc/require-template': 'off',
205
325
  'jsdoc/require-throws': 'off',
326
+ 'jsdoc/require-throws-type': warnOrError,
206
327
  'jsdoc/require-yields': warnOrError,
207
328
  'jsdoc/require-yields-check': warnOrError,
329
+ 'jsdoc/require-yields-type': warnOrError,
208
330
  'jsdoc/sort-tags': 'off',
209
331
  'jsdoc/tag-lines': warnOrError,
210
332
  'jsdoc/text-escaping': 'off',
@@ -338,6 +460,7 @@ const createLogicalTypescriptFlavorRuleset = createStandaloneRulesetFactory(logi
338
460
  const requirementsRules = [
339
461
  'jsdoc/require-example',
340
462
  'jsdoc/require-jsdoc',
463
+ 'jsdoc/require-next-type',
341
464
  'jsdoc/require-param',
342
465
  'jsdoc/require-param-description',
343
466
  'jsdoc/require-param-name',
@@ -346,7 +469,9 @@ const requirementsRules = [
346
469
  'jsdoc/require-property-name',
347
470
  'jsdoc/require-returns',
348
471
  'jsdoc/require-returns-description',
472
+ 'jsdoc/require-throws-type',
349
473
  'jsdoc/require-yields',
474
+ 'jsdoc/require-yields-type',
350
475
  ];
351
476
 
352
477
  const createRequirementsTypeScriptRuleset = createStandaloneRulesetFactory(requirementsRules);
package/src/index-esm.js CHANGED
@@ -4,7 +4,9 @@ import {
4
4
  } from 'object-deep-merge';
5
5
 
6
6
  // BEGIN REPLACE
7
- import index from './index-cjs.js';
7
+ import index, {
8
+ buildForbidRuleDefinition,
9
+ } from './index-cjs.js';
8
10
 
9
11
  // eslint-disable-next-line unicorn/prefer-export-from --- Reusing `index`
10
12
  export default index;
@@ -14,10 +16,23 @@ export default index;
14
16
  /**
15
17
  * @type {((
16
18
  * cfg?: import('eslint').Linter.Config & {
17
- * mergeSettings?: boolean,
18
19
  * config?: `flat/${import('./index-cjs.js').ConfigGroups}${import('./index-cjs.js').ConfigVariants}${import('./index-cjs.js').ErrorLevelVariants}`,
20
+ * mergeSettings?: boolean,
19
21
  * settings?: Partial<import('./iterateJsdoc.js').Settings>,
20
- * rules?: {[key in keyof import('./rules.d.ts').Rules]?: import('eslint').Linter.RuleEntry<import('./rules.d.ts').Rules[key]>}
22
+ * rules?: {[key in keyof import('./rules.d.ts').Rules]?: import('eslint').Linter.RuleEntry<import('./rules.d.ts').Rules[key]>},
23
+ * extraRuleDefinitions?: {
24
+ * forbid: {
25
+ * [contextName: string]: {
26
+ * description?: string,
27
+ * url?: string,
28
+ * contexts: (string|{
29
+ * message: string,
30
+ * context: string,
31
+ * comment: string
32
+ * })[]
33
+ * }
34
+ * }
35
+ * }
21
36
  * }
22
37
  * ) => import('eslint').Linter.Config)}
23
38
  */
@@ -85,6 +100,31 @@ export const jsdoc = function (cfg) {
85
100
  if (cfg.processor) {
86
101
  outputConfig.processor = cfg.processor;
87
102
  }
103
+
104
+ if (cfg.extraRuleDefinitions) {
105
+ if (!outputConfig.plugins?.jsdoc?.rules) {
106
+ throw new Error('JSDoc plugin required for `extraRuleDefinitions`');
107
+ }
108
+
109
+ if (cfg.extraRuleDefinitions.forbid) {
110
+ for (const [
111
+ contextName,
112
+ {
113
+ contexts,
114
+ description,
115
+ url,
116
+ },
117
+ ] of Object.entries(cfg.extraRuleDefinitions.forbid)) {
118
+ outputConfig.plugins.jsdoc.rules[`forbid-${contextName}`] =
119
+ buildForbidRuleDefinition({
120
+ contextName,
121
+ contexts,
122
+ description,
123
+ url,
124
+ });
125
+ }
126
+ }
127
+ }
88
128
  }
89
129
 
90
130
  outputConfig.settings = {
@@ -103,16 +143,6 @@ export const jsdoc = function (cfg) {
103
143
  'type',
104
144
  ],
105
145
  },
106
- throws: {
107
- required: [
108
- 'type',
109
- ],
110
- },
111
- yields: {
112
- required: [
113
- 'type',
114
- ],
115
- },
116
146
  },
117
147
  } :
118
148
  {},
package/src/index.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  import {
8
8
  getJsdocProcessorPlugin,
9
9
  } from './getJsdocProcessorPlugin.js';
10
+ import iterateJsdoc from './iterateJsdoc.js';
10
11
  import checkAccess from './rules/checkAccess.js';
11
12
  import checkAlignment from './rules/checkAlignment.js';
12
13
  import checkExamples from './rules/checkExamples.js';
@@ -66,6 +67,91 @@ import textEscaping from './rules/textEscaping.js';
66
67
  import typeFormatting from './rules/typeFormatting.js';
67
68
  import validTypes from './rules/validTypes.js';
68
69
 
70
+ /**
71
+ * @param {{
72
+ * contexts: (string|{
73
+ * comment: string,
74
+ * context: string,
75
+ * message: string
76
+ * })[],
77
+ * description?: string,
78
+ * contextName?: string
79
+ * url?: string,
80
+ * }} cfg
81
+ * @returns {import('@eslint/core').RuleDefinition<
82
+ * import('@eslint/core').RuleDefinitionTypeOptions
83
+ * >}
84
+ */
85
+ export const buildForbidRuleDefinition = ({
86
+ contextName,
87
+ contexts,
88
+ description,
89
+ url,
90
+ }) => {
91
+ return iterateJsdoc(({
92
+ // context,
93
+ info: {
94
+ comment,
95
+ },
96
+ report,
97
+ utils,
98
+ }) => {
99
+ const {
100
+ contextStr,
101
+ foundContext,
102
+ } = utils.findContext(contexts, comment);
103
+
104
+ // We are not on the *particular* matching context/comment, so don't assume
105
+ // we need reporting
106
+ if (!foundContext) {
107
+ return;
108
+ }
109
+
110
+ const message = /** @type {import('./iterateJsdoc.js').ContextObject} */ (
111
+ foundContext
112
+ )?.message ??
113
+ 'Syntax is restricted: {{context}}' +
114
+ (comment ? ' with {{comment}}' : '');
115
+
116
+ report(message, null, null, comment ? {
117
+ comment,
118
+ context: contextStr,
119
+ } : {
120
+ context: contextStr,
121
+ });
122
+ }, {
123
+ contextSelected: true,
124
+ meta: {
125
+ docs: {
126
+ description: description ?? contextName ?? 'Reports when certain comment structures are present.',
127
+ url: url ?? 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-restricted-syntax.md#repos-sticky-header',
128
+ },
129
+ fixable: 'code',
130
+ schema: [],
131
+ type: 'suggestion',
132
+ },
133
+ modifyContext: (context) => {
134
+ // Reproduce context object with our own `contexts`
135
+ const propertyDescriptors = Object.getOwnPropertyDescriptors(context);
136
+ return Object.create(
137
+ Object.getPrototypeOf(context),
138
+ {
139
+ ...propertyDescriptors,
140
+ options: {
141
+ ...propertyDescriptors.options,
142
+ value: [
143
+ {
144
+ contexts,
145
+ },
146
+ ],
147
+ },
148
+ },
149
+ );
150
+ },
151
+ nonGlobalSettings: true,
152
+ });
153
+ };
154
+
69
155
  /* eslint-disable jsdoc/valid-types -- Bug */
70
156
  /**
71
157
  * @typedef {"recommended" | "stylistic" | "contents" | "logical" | "requirements"} ConfigGroups
@@ -117,6 +203,17 @@ index.rules = {
117
203
  'require-file-overview': requireFileOverview,
118
204
  'require-hyphen-before-param-description': requireHyphenBeforeParamDescription,
119
205
  'require-jsdoc': requireJsdoc,
206
+ 'require-next-type': buildForbidRuleDefinition({
207
+ contexts: [
208
+ {
209
+ comment: 'JsdocBlock:has(JsdocTag[tag=next]:not([parsedType.type]))',
210
+ context: 'any',
211
+ message: '@next should have a type',
212
+ },
213
+ ],
214
+ description: 'Requires a type for @next tags',
215
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-next-type.md#repos-sticky-header',
216
+ }),
120
217
  'require-param': requireParam,
121
218
  'require-param-description': requireParamDescription,
122
219
  'require-param-name': requireParamName,
@@ -131,8 +228,30 @@ index.rules = {
131
228
  'require-returns-type': requireReturnsType,
132
229
  'require-template': requireTemplate,
133
230
  'require-throws': requireThrows,
231
+ 'require-throws-type': buildForbidRuleDefinition({
232
+ contexts: [
233
+ {
234
+ comment: 'JsdocBlock:has(JsdocTag[tag=throws]:not([parsedType.type]))',
235
+ context: 'any',
236
+ message: '@throws should have a type',
237
+ },
238
+ ],
239
+ description: 'Requires a type for @throws tags',
240
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-throws-type.md#repos-sticky-header',
241
+ }),
134
242
  'require-yields': requireYields,
135
243
  'require-yields-check': requireYieldsCheck,
244
+ 'require-yields-type': buildForbidRuleDefinition({
245
+ contexts: [
246
+ {
247
+ comment: 'JsdocBlock:has(JsdocTag[tag=yields]:not([parsedType.type]))',
248
+ context: 'any',
249
+ message: '@yields should have a type',
250
+ },
251
+ ],
252
+ description: 'Requires a type for @yields tags',
253
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-yields-type.md#repos-sticky-header',
254
+ }),
136
255
  'sort-tags': sortTags,
137
256
  'tag-lines': tagLines,
138
257
  'text-escaping': textEscaping,
@@ -195,6 +314,7 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
195
314
  'jsdoc/require-file-overview': 'off',
196
315
  'jsdoc/require-hyphen-before-param-description': 'off',
197
316
  'jsdoc/require-jsdoc': warnOrError,
317
+ 'jsdoc/require-next-type': warnOrError,
198
318
  'jsdoc/require-param': warnOrError,
199
319
  'jsdoc/require-param-description': warnOrError,
200
320
  'jsdoc/require-param-name': warnOrError,
@@ -209,8 +329,10 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
209
329
  'jsdoc/require-returns-type': warnOrError,
210
330
  'jsdoc/require-template': 'off',
211
331
  'jsdoc/require-throws': 'off',
332
+ 'jsdoc/require-throws-type': warnOrError,
212
333
  'jsdoc/require-yields': warnOrError,
213
334
  'jsdoc/require-yields-check': warnOrError,
335
+ 'jsdoc/require-yields-type': warnOrError,
214
336
  'jsdoc/sort-tags': 'off',
215
337
  'jsdoc/tag-lines': warnOrError,
216
338
  'jsdoc/text-escaping': 'off',
@@ -344,6 +466,7 @@ const createLogicalTypescriptFlavorRuleset = createStandaloneRulesetFactory(logi
344
466
  const requirementsRules = [
345
467
  'jsdoc/require-example',
346
468
  'jsdoc/require-jsdoc',
469
+ 'jsdoc/require-next-type',
347
470
  'jsdoc/require-param',
348
471
  'jsdoc/require-param-description',
349
472
  'jsdoc/require-param-name',
@@ -352,7 +475,9 @@ const requirementsRules = [
352
475
  'jsdoc/require-property-name',
353
476
  'jsdoc/require-returns',
354
477
  'jsdoc/require-returns-description',
478
+ 'jsdoc/require-throws-type',
355
479
  'jsdoc/require-yields',
480
+ 'jsdoc/require-yields-type',
356
481
  ];
357
482
 
358
483
  const createRequirementsTypeScriptRuleset = createStandaloneRulesetFactory(requirementsRules);
@@ -540,10 +665,23 @@ export default index;
540
665
  /**
541
666
  * @type {((
542
667
  * cfg?: import('eslint').Linter.Config & {
543
- * mergeSettings?: boolean,
544
668
  * config?: `flat/${ConfigGroups}${ConfigVariants}${ErrorLevelVariants}`,
669
+ * mergeSettings?: boolean,
545
670
  * settings?: Partial<import('./iterateJsdoc.js').Settings>,
546
- * rules?: {[key in keyof import('./rules.d.ts').Rules]?: import('eslint').Linter.RuleEntry<import('./rules.d.ts').Rules[key]>}
671
+ * rules?: {[key in keyof import('./rules.d.ts').Rules]?: import('eslint').Linter.RuleEntry<import('./rules.d.ts').Rules[key]>},
672
+ * extraRuleDefinitions?: {
673
+ * forbid: {
674
+ * [contextName: string]: {
675
+ * description?: string,
676
+ * url?: string,
677
+ * contexts: (string|{
678
+ * message: string,
679
+ * context: string,
680
+ * comment: string
681
+ * })[]
682
+ * }
683
+ * }
684
+ * }
547
685
  * }
548
686
  * ) => import('eslint').Linter.Config)}
549
687
  */
@@ -611,6 +749,31 @@ export const jsdoc = function (cfg) {
611
749
  if (cfg.processor) {
612
750
  outputConfig.processor = cfg.processor;
613
751
  }
752
+
753
+ if (cfg.extraRuleDefinitions) {
754
+ if (!outputConfig.plugins?.jsdoc?.rules) {
755
+ throw new Error('JSDoc plugin required for `extraRuleDefinitions`');
756
+ }
757
+
758
+ if (cfg.extraRuleDefinitions.forbid) {
759
+ for (const [
760
+ contextName,
761
+ {
762
+ contexts,
763
+ description,
764
+ url,
765
+ },
766
+ ] of Object.entries(cfg.extraRuleDefinitions.forbid)) {
767
+ outputConfig.plugins.jsdoc.rules[`forbid-${contextName}`] =
768
+ buildForbidRuleDefinition({
769
+ contextName,
770
+ contexts,
771
+ description,
772
+ url,
773
+ });
774
+ }
775
+ }
776
+ }
614
777
  }
615
778
 
616
779
  outputConfig.settings = {
@@ -629,16 +792,6 @@ export const jsdoc = function (cfg) {
629
792
  'type',
630
793
  ],
631
794
  },
632
- throws: {
633
- required: [
634
- 'type',
635
- ],
636
- },
637
- yields: {
638
- required: [
639
- 'type',
640
- ],
641
- },
642
795
  },
643
796
  } :
644
797
  {},