eslint-plugin-jsdoc 56.1.2 → 57.0.0

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 +9 -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 +103 -3
  7. package/dist/index-cjs.cjs.map +1 -1
  8. package/dist/index-cjs.d.ts +9 -0
  9. package/dist/index-esm.cjs +33 -10
  10. package/dist/index-esm.cjs.map +1 -1
  11. package/dist/index-esm.d.ts +27 -3
  12. package/dist/index.cjs +134 -10
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.ts +36 -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 +120 -0
  39. package/src/index-esm.js +40 -13
  40. package/src/index.js +157 -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":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,OAAO;EACPC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,MAAM,CACJC,WAAW,GAAG,OAAO,EACrB;IACEC,aAAa,GAAG,IAAI;IACpBC,KAAK,GAAG,CAAC;IACTC,QAAQ,GAAG,CAAC;IACZC,UAAU,GAAG,CAAC;IACdC,IAAI,GAAG,CAAC;EACV,CAAC,GAAG,CAAC,CAAC,CACP,GAAGR,OAAO,CAACS,OAAO;;EAEnB;EACAR,KAAK,CAACO,IAAI,CAACE,IAAI,CAAC,CAACC,EAAE,EAAEC,MAAM,KAAK;IAC9B,IAAIC,OAAO;;IAEX;AACJ;AACA;IACI,IAAIC,SAAS,GAAG,IAAI;;IAEpB;AACJ;AACA;IACI,IAAIC,WAAW,GAAG,IAAI;IACtB,IAAIC,eAAe,GAAG,CAAC;IACvB,KAAK,MAAM,CACTC,GAAG,EACH;MACEC,MAAM,EAAE;QACNC,WAAW;QACXC,GAAG;QACHC,IAAI;QACJC,GAAG;QACHC;MACF;IACF,CAAC,CACF,IAAIZ,EAAE,CAACa,MAAM,CAACC,OAAO,CAAC,CAAC,EAAE;MACxB;MACA,IAAIN,WAAW,EAAE;QACfJ,WAAW,GAAG,IAAI;MACpB;MAEA,IAAIF,OAAO,IAAI,CACb,QAAQ,EAAE,KAAK,CAChB,CAACa,QAAQ,CAAClB,IAAI,CAACK,OAAO,CAACc,KAAK,CAAC,CAAC,CAAC,CAAC,EAAEC,KAAK,CAAC,EAAE;QACzC;MACF;MAEA,MAAMC,KAAK,GAAG,CAACP,GAAG,IAAI,CAACD,IAAI,IAAI,CAACE,IAAI,IAAI,CAACJ,WAAW;MACpD,IACEU,KAAK,IAAI,CAACT,GAAG,KACZjB,WAAW,KAAK,OAAO,IACtBU,OAAO,IAAIL,IAAI,CAACK,OAAO,CAACc,KAAK,CAAC,CAAC,CAAC,CAAC,EAAEC,KAAK,KAAK,OAAO,CACrD,EACD;QACAb,WAAW,GAAGE,GAAG;QAEjB;MACF;MAEA,IAAI,CAACG,GAAG,EAAE;QACR,IAAIS,KAAK,EAAE;UACTb,eAAe,EAAE;QACnB,CAAC,MAAM;UACLA,eAAe,GAAG,CAAC;QACrB;QAEAF,SAAS,GAAGe,KAAK,GAAGZ,GAAG,GAAG,IAAI;MAChC;MAEAJ,OAAO,GAAGS,GAAG;IACf;IAEA,IACE,OAAOhB,QAAQ,KAAK,QAAQ,IAC5BQ,SAAS,KAAK,IAAI,IAAIF,MAAM,KAAKX,KAAK,CAACO,IAAI,CAACsB,MAAM,GAAG,CAAC,EACtD;MACA,MAAMC,QAAQ,GAAGzB,QAAQ,GAAGU,eAAe;MAE3C,IAAIe,QAAQ,GAAG,CAAC,EAAE;QAChB,MAAMC,KAAK,GAAGA,CAAA,KAAM;UAClB9B,KAAK,CAAC+B,SAAS,CAACrB,MAAM,EAAE;YACtBsB,eAAe,EAAE,mDACfpB,SAAS,GACPiB,QAAQ,GAAG;UACjB,CAAC,CAAC;QACJ,CAAC;QAED7B,KAAK,CAACiC,WAAW,CACf,YAAY7B,QAAQ,iBAAiB,EACrC;UACE8B,IAAI,EAAEzB,EAAE,CAACa,MAAM,CAACV,SAAS,CAAC,CAACuB,MAAM,GAAGN,QAAQ,GAAG;QACjD,CAAC,EACDC,KACF,CAAC;MACH,CAAC,MAAM,IAAID,QAAQ,GAAG,CAAC,EAAE;QACvB,MAAMC,KAAK,GAAGA,CAAA,KAAM;UAClB9B,KAAK,CAACoC,QAAQ,CACZ1B,MAAM,EACN,mDAAqDE,SAAS,EAC9DR,QAAQ,GAAGU,eACb,CAAC;QACH,CAAC;QAEDd,KAAK,CAACiC,WAAW,CACf,YAAY7B,QAAQ,iBAAiB,EACrC;UACE8B,IAAI,EAAEzB,EAAE,CAACa,MAAM,CAACV,SAAS,CAAC,CAACuB;QAC7B,CAAC,EACDL,KACF,CAAC;MACH;MAEA,OAAO,IAAI;IACb;IAEA,IAAIjB,WAAW,KAAK,IAAI,EAAE;MACxB,MAAMiB,KAAK,GAAGA,CAAA,KAAM;QAClB9B,KAAK,CAAC+B,SAAS,CAACrB,MAAM,EAAE;UACtBsB,eAAe,GAAE;UACfnB,WAAW;QAEf,CAAC,CAAC;MACJ,CAAC;MAEDb,KAAK,CAACiC,WAAW,CACf,gCAAgC,EAChC;QACEC,IAAI,EAAEzB,EAAE,CAACa,MAAM,CAAC,CAAC,CAAC,CAACa,MAAM,GAAG;MAC9B,CAAC,EACDL,KACF,CAAC;MAED,OAAO,IAAI;IACb;IAEA,OAAO,KAAK;EACd,CAAC,CAAC;EAEF,CAAC5B,aAAa,GAAGH,KAAK,CAACO,IAAI,GAAGP,KAAK,CAACO,IAAI,CAACmB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAEjB,IAAI,CAAC,CAACC,EAAE,EAAEC,MAAM,KAAK;IAC1E;AACJ;AACA;AACA;AACA;AACA;IACI,MAAMgB,KAAK,GAAG,EAAE;IAEhB,IAAIW,UAAU;IACd,IAAIC,YAAY,GAAG,CAAC;IACpB,KAAK,MAAM,CACTvB,GAAG,EACH;MACEoB,MAAM;MACNnB,MAAM,EAAE;QACNC,WAAW;QACXC,GAAG;QACHC,IAAI;QACJC,GAAG;QACHC;MACF;IACF,CAAC,CACF,IAAIZ,EAAE,CAACa,MAAM,CAACC,OAAO,CAAC,CAAC,EAAE;MACxB,IAAIN,WAAW,EAAE;QACfS,KAAK,CAACa,MAAM,CAAC,CAAC,CAAC;QACfD,YAAY,GAAGvB,GAAG;MACpB;MAEA,IAAIK,GAAG,EAAE;QACPiB,UAAU,GAAGjB,GAAG;MAClB;MAEA,IAAI,CAACA,GAAG,IAAI,CAACD,IAAI,IAAI,CAACE,IAAI,IAAI,CAACJ,WAAW,IAAI,CAACC,GAAG,EAAE;QAClDQ,KAAK,CAACc,IAAI,CAAC;UACTzB,GAAG;UACHoB;QACF,CAAC,CAAC;MACJ;IACF;IAEA,MAAMM,SAAS,GAAGJ,UAAU,IAAI/B,IAAI,CAAC+B,UAAU,CAACZ,KAAK,CAAC,CAAC,CAAC,CAAC;IACzD,MAAMiB,QAAQ,GAAGD,SAAS,EAAEtC,KAAK;IAEjC,MAAMwC,aAAa,GAAG1C,WAAW,KAAK,QAAQ,IAAIwC,SAAS,EAAEf,KAAK,KAAK,OAAO,IAC5Ee,SAAS,EAAEf,KAAK,KAAK,KAAK,IAAIA,KAAK,CAACE,MAAM,GAAGzB,KAAK;IAEpD,IAAIyC,cAAc;IAClB,IAAIC,QAAQ,GAAG1C,KAAK;IACpB,IAAI,CAACwC,aAAa,EAAE;MAClBE,QAAQ,GAAG,OAAOH,QAAQ,KAAK,QAAQ,GAAGA,QAAQ,GAAGvC,KAAK;MAC1DyC,cAAc,GAAGH,SAAS,EAAEf,KAAK,KAAK,QAAQ,IAC5CA,KAAK,CAACE,MAAM,GAAGiB,QAAQ;IAC3B;IAEA,IAAIF,aAAa,IAAIC,cAAc,EAAE;MACnC,MAAMd,KAAK,GAAGA,CAAA,KAAM;QAClB9B,KAAK,CAACoC,QAAQ,CAAC1B,MAAM,EAAEgB,KAAK,CAACA,KAAK,CAACE,MAAM,GAAG,CAAC,CAAC,EAAEb,GAAG,IAAIuB,YAAY,GAAG,CAAC,EAAEO,QAAQ,GAAGnB,KAAK,CAACE,MAAM,CAAC;MACnG,CAAC;MAED,MAAMM,IAAI,GAAGR,KAAK,CAACA,KAAK,CAACE,MAAM,GAAG,CAAC,CAAC,EAAEO,MAAM,IAAI1B,EAAE,CAACa,MAAM,CAACgB,YAAY,CAAC,CAACH,MAAM;MAC9EnC,KAAK,CAACiC,WAAW,CACf,YAAYY,QAAQ,QAAQA,QAAQ,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,2BAA2BnB,KAAK,CAACE,MAAM,EAAE,EAC9F;QACEM;MACF,CAAC,EACDJ,KACF,CAAC;MAED,OAAO,IAAI;IACb;IAEA,OAAO,KAAK;EACd,CAAC,CAAC;EAEF,IAAI,OAAOzB,UAAU,KAAK,QAAQ,EAAE;IAClC,IAAI,CAACN,KAAK,CAACO,IAAI,CAACsB,MAAM,EAAE;MACtB;IACF;IAEA,MAAM;MACJX,WAAW;MACX6B;IACF,CAAC,GAAG9C,KAAK,CAAC+C,cAAc,CAAC,CAAC;IAC1B,IAAI,CAAE,KAAK,CAAEC,IAAI,CAAC/B,WAAW,CAAC,EAAE;MAC9B;IACF;IAEA,MAAMgC,aAAa,GAAGhC,WAAW,CAACiC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAEtB,MAAM;IAC7D,MAAMuB,YAAY,GAAG,CAACF,aAAa,IAAI,CAAC,IAAI5C,UAAU;IACtD,IAAI8C,YAAY,GAAG,CAAC,EAAE;MACpBnD,KAAK,CAACiC,WAAW,CACf,iBAAiB5B,UAAU,+BAA+B,EAC1D;QACE6B,IAAI,EAAEY,mBAAmB,GAAGK;MAC9B,CAAC,EACD,MAAM;QACJnD,KAAK,CAACoD,mBAAmB,CAAC,CAACC,IAAI,EAAEC,UAAU,EAAEC,SAAS,KAAK;UACzD,OAAOA,SAAS,CAAC9B,KAAK,CAAC,CAAC,EAAE,CAAC0B,YAAY,CAAC,CAACK,GAAG,CAAEC,IAAI,IAAK;YACrD,OAAO;cACLtB,MAAM,EAAE,CAAC;cACTb,MAAM,EAAE,EAAE;cACVN,MAAM,EAAEsC,UAAU,CAAC;gBACjB,GAAGD,IAAI;gBACPpC,WAAW,EAAEwC,IAAI;gBACjBC,aAAa,EAAED,IAAI,CAACE,IAAI,CAAC,CAAC,GAAGN,IAAI,CAACK,aAAa,GAAG;cACpD,CAAC;YACH,CAAC;UACH,CAAC,CAAC;QACJ,CAAC,CAAC;MACJ,CACF,CAAC;IACH,CAAC,MAAM,IAAIP,YAAY,GAAG,CAAC,EAAE;MAC3BnD,KAAK,CAACiC,WAAW,CACf,YAAY5B,UAAU,gCAAgC,EACtD;QACE6B,IAAI,EAAEY;MACR,CAAC,EACD,MAAM;QACJ9C,KAAK,CAACoD,mBAAmB,CAAC,CAACC,IAAI,EAAEC,UAAU,EAAEC,SAAS,KAAK;UACzD,OAAO,CACL,GAAGA,SAAS,EACZ,GAAGK,KAAK,CAACC,IAAI,CAAC;YACZjC,MAAM,EAAE,CAACuB;UACX,CAAC,EAAE,MAAM;YACP,OAAO,EAAE;UACX,CAAC,CAAC,CACH,CAACK,GAAG,CAAEC,IAAI,IAAK;YACd,OAAO;cACLtB,MAAM,EAAE,CAAC;cACTb,MAAM,EAAE,EAAE;cACVN,MAAM,EAAEsC,UAAU,CAAC;gBACjB,GAAGD,IAAI;gBACPpC,WAAW,EAAEwC,IAAI;gBACjBC,aAAa,EAAED,IAAI,CAACE,IAAI,CAAC,CAAC,GAAGN,IAAI,CAACK,aAAa,GAAG;cACpD,CAAC;YACH,CAAC;UACH,CAAC,CAAC;QACJ,CAAC,CAAC;MACJ,CACF,CAAC;IACH;EACF;AACF,CAAC,EAAE;EACDI,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJ/C,WAAW,EAAE,4CAA4C;MACzDgD,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,MAAM,EAAE,CACN;MACEC,IAAI,EAAE,CACJ,QAAQ,EAAE,KAAK,EAAE,OAAO,CACzB;MACD/C,IAAI,EAAE;IACR,CAAC,EACD;MACEgD,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVpE,aAAa,EAAE;UACbmB,IAAI,EAAE;QACR,CAAC;QACDlB,KAAK,EAAE;UACLkB,IAAI,EAAE;QACR,CAAC;QACDjB,QAAQ,EAAE;UACRmE,KAAK,EAAE,CACL;YACElD,IAAI,EAAE;UACR,CAAC,EACD;YACEA,IAAI,EAAE;UACR,CAAC;QAEL,CAAC;QACDhB,UAAU,EAAE;UACVkE,KAAK,EAAE,CACL;YACElD,IAAI,EAAE;UACR,CAAC,EACD;YACEA,IAAI,EAAE;UACR,CAAC;QAEL,CAAC;QACDf,IAAI,EAAE;UACJkE,iBAAiB,EAAE;YACjB,IAAI,EAAE;cACJH,oBAAoB,EAAE,KAAK;cAC3BC,UAAU,EAAE;gBACVnE,KAAK,EAAE;kBACLkB,IAAI,EAAE;gBACR,CAAC;gBACDK,KAAK,EAAE;kBACL0C,IAAI,EAAE,CACJ,QAAQ,EAAE,OAAO,EAAE,KAAK,CACzB;kBACD/C,IAAI,EAAE;gBACR;cACF;YACF;UACF,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAoD,MAAA,CAAA7E,OAAA,GAAAA,OAAA,CAAAF,OAAA","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.0"
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,89 @@ 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
+ * }} cfg
74
+ * @returns {import('@eslint/core').RuleDefinition<
75
+ * import('@eslint/core').RuleDefinitionTypeOptions
76
+ * >}
77
+ */
78
+ export const buildForbidRuleDefinition = ({
79
+ contextName,
80
+ contexts,
81
+ description,
82
+ }) => {
83
+ return iterateJsdoc(({
84
+ // context,
85
+ info: {
86
+ comment,
87
+ },
88
+ report,
89
+ utils,
90
+ }) => {
91
+ const {
92
+ contextStr,
93
+ foundContext,
94
+ } = utils.findContext(contexts, comment);
95
+
96
+ // We are not on the *particular* matching context/comment, so don't assume
97
+ // we need reporting
98
+ if (!foundContext) {
99
+ return;
100
+ }
101
+
102
+ const message = /** @type {import('./iterateJsdoc.js').ContextObject} */ (
103
+ foundContext
104
+ )?.message ??
105
+ 'Syntax is restricted: {{context}}' +
106
+ (comment ? ' with {{comment}}' : '');
107
+
108
+ report(message, null, null, comment ? {
109
+ comment,
110
+ context: contextStr,
111
+ } : {
112
+ context: contextStr,
113
+ });
114
+ }, {
115
+ contextSelected: true,
116
+ meta: {
117
+ docs: {
118
+ description: description ?? contextName ?? 'Reports when certain comment structures are present.',
119
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-restricted-syntax.md#repos-sticky-header',
120
+ },
121
+ fixable: 'code',
122
+ schema: [],
123
+ type: 'suggestion',
124
+ },
125
+ modifyContext: (context) => {
126
+ // Reproduce context object with our own `contexts`
127
+ const propertyDescriptors = Object.getOwnPropertyDescriptors(context);
128
+ return Object.create(
129
+ Object.getPrototypeOf(context),
130
+ {
131
+ ...propertyDescriptors,
132
+ options: {
133
+ ...propertyDescriptors.options,
134
+ value: [
135
+ {
136
+ contexts,
137
+ },
138
+ ],
139
+ },
140
+ },
141
+ );
142
+ },
143
+ nonGlobalSettings: true,
144
+ });
145
+ };
146
+
63
147
  /* eslint-disable jsdoc/valid-types -- Bug */
64
148
  /**
65
149
  * @typedef {"recommended" | "stylistic" | "contents" | "logical" | "requirements"} ConfigGroups
@@ -111,6 +195,16 @@ index.rules = {
111
195
  'require-file-overview': requireFileOverview,
112
196
  'require-hyphen-before-param-description': requireHyphenBeforeParamDescription,
113
197
  'require-jsdoc': requireJsdoc,
198
+ 'require-next-type': buildForbidRuleDefinition({
199
+ contexts: [
200
+ {
201
+ comment: 'JsdocBlock:has(JsdocTag[tag=next]:not([parsedType.type]))',
202
+ context: 'any',
203
+ message: '@next should have a type',
204
+ },
205
+ ],
206
+ description: 'Requires a type for @next tags',
207
+ }),
114
208
  'require-param': requireParam,
115
209
  'require-param-description': requireParamDescription,
116
210
  'require-param-name': requireParamName,
@@ -125,8 +219,28 @@ index.rules = {
125
219
  'require-returns-type': requireReturnsType,
126
220
  'require-template': requireTemplate,
127
221
  'require-throws': requireThrows,
222
+ 'require-throws-type': buildForbidRuleDefinition({
223
+ contexts: [
224
+ {
225
+ comment: 'JsdocBlock:has(JsdocTag[tag=throws]:not([parsedType.type]))',
226
+ context: 'any',
227
+ message: '@throws should have a type',
228
+ },
229
+ ],
230
+ description: 'Requires a type for @throws tags',
231
+ }),
128
232
  'require-yields': requireYields,
129
233
  'require-yields-check': requireYieldsCheck,
234
+ 'require-yields-type': buildForbidRuleDefinition({
235
+ contexts: [
236
+ {
237
+ comment: 'JsdocBlock:has(JsdocTag[tag=yields]:not([parsedType.type]))',
238
+ context: 'any',
239
+ message: '@yields should have a type',
240
+ },
241
+ ],
242
+ description: 'Requires a type for @yields tags',
243
+ }),
130
244
  'sort-tags': sortTags,
131
245
  'tag-lines': tagLines,
132
246
  'text-escaping': textEscaping,
@@ -189,6 +303,7 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
189
303
  'jsdoc/require-file-overview': 'off',
190
304
  'jsdoc/require-hyphen-before-param-description': 'off',
191
305
  'jsdoc/require-jsdoc': warnOrError,
306
+ 'jsdoc/require-next-type': warnOrError,
192
307
  'jsdoc/require-param': warnOrError,
193
308
  'jsdoc/require-param-description': warnOrError,
194
309
  'jsdoc/require-param-name': warnOrError,
@@ -203,8 +318,10 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
203
318
  'jsdoc/require-returns-type': warnOrError,
204
319
  'jsdoc/require-template': 'off',
205
320
  'jsdoc/require-throws': 'off',
321
+ 'jsdoc/require-throws-type': warnOrError,
206
322
  'jsdoc/require-yields': warnOrError,
207
323
  'jsdoc/require-yields-check': warnOrError,
324
+ 'jsdoc/require-yields-type': warnOrError,
208
325
  'jsdoc/sort-tags': 'off',
209
326
  'jsdoc/tag-lines': warnOrError,
210
327
  'jsdoc/text-escaping': 'off',
@@ -338,6 +455,7 @@ const createLogicalTypescriptFlavorRuleset = createStandaloneRulesetFactory(logi
338
455
  const requirementsRules = [
339
456
  'jsdoc/require-example',
340
457
  'jsdoc/require-jsdoc',
458
+ 'jsdoc/require-next-type',
341
459
  'jsdoc/require-param',
342
460
  'jsdoc/require-param-description',
343
461
  'jsdoc/require-param-name',
@@ -346,7 +464,9 @@ const requirementsRules = [
346
464
  'jsdoc/require-property-name',
347
465
  'jsdoc/require-returns',
348
466
  'jsdoc/require-returns-description',
467
+ 'jsdoc/require-throws-type',
349
468
  'jsdoc/require-yields',
469
+ 'jsdoc/require-yields-type',
350
470
  ];
351
471
 
352
472
  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,22 @@ 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
+ * contexts: (string|{
28
+ * message: string,
29
+ * context: string,
30
+ * comment: string
31
+ * })[]
32
+ * }
33
+ * }
34
+ * }
21
35
  * }
22
36
  * ) => import('eslint').Linter.Config)}
23
37
  */
@@ -85,6 +99,29 @@ export const jsdoc = function (cfg) {
85
99
  if (cfg.processor) {
86
100
  outputConfig.processor = cfg.processor;
87
101
  }
102
+
103
+ if (cfg.extraRuleDefinitions) {
104
+ if (!outputConfig.plugins?.jsdoc?.rules) {
105
+ throw new Error('JSDoc plugin required for `extraRuleDefinitions`');
106
+ }
107
+
108
+ if (cfg.extraRuleDefinitions.forbid) {
109
+ for (const [
110
+ contextName,
111
+ {
112
+ contexts,
113
+ description,
114
+ },
115
+ ] of Object.entries(cfg.extraRuleDefinitions.forbid)) {
116
+ outputConfig.plugins.jsdoc.rules[`forbid-${contextName}`] =
117
+ buildForbidRuleDefinition({
118
+ contextName,
119
+ contexts,
120
+ description,
121
+ });
122
+ }
123
+ }
124
+ }
88
125
  }
89
126
 
90
127
  outputConfig.settings = {
@@ -103,16 +140,6 @@ export const jsdoc = function (cfg) {
103
140
  'type',
104
141
  ],
105
142
  },
106
- throws: {
107
- required: [
108
- 'type',
109
- ],
110
- },
111
- yields: {
112
- required: [
113
- 'type',
114
- ],
115
- },
116
143
  },
117
144
  } :
118
145
  {},
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,89 @@ 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
+ * }} cfg
80
+ * @returns {import('@eslint/core').RuleDefinition<
81
+ * import('@eslint/core').RuleDefinitionTypeOptions
82
+ * >}
83
+ */
84
+ export const buildForbidRuleDefinition = ({
85
+ contextName,
86
+ contexts,
87
+ description,
88
+ }) => {
89
+ return iterateJsdoc(({
90
+ // context,
91
+ info: {
92
+ comment,
93
+ },
94
+ report,
95
+ utils,
96
+ }) => {
97
+ const {
98
+ contextStr,
99
+ foundContext,
100
+ } = utils.findContext(contexts, comment);
101
+
102
+ // We are not on the *particular* matching context/comment, so don't assume
103
+ // we need reporting
104
+ if (!foundContext) {
105
+ return;
106
+ }
107
+
108
+ const message = /** @type {import('./iterateJsdoc.js').ContextObject} */ (
109
+ foundContext
110
+ )?.message ??
111
+ 'Syntax is restricted: {{context}}' +
112
+ (comment ? ' with {{comment}}' : '');
113
+
114
+ report(message, null, null, comment ? {
115
+ comment,
116
+ context: contextStr,
117
+ } : {
118
+ context: contextStr,
119
+ });
120
+ }, {
121
+ contextSelected: true,
122
+ meta: {
123
+ docs: {
124
+ description: description ?? contextName ?? 'Reports when certain comment structures are present.',
125
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-restricted-syntax.md#repos-sticky-header',
126
+ },
127
+ fixable: 'code',
128
+ schema: [],
129
+ type: 'suggestion',
130
+ },
131
+ modifyContext: (context) => {
132
+ // Reproduce context object with our own `contexts`
133
+ const propertyDescriptors = Object.getOwnPropertyDescriptors(context);
134
+ return Object.create(
135
+ Object.getPrototypeOf(context),
136
+ {
137
+ ...propertyDescriptors,
138
+ options: {
139
+ ...propertyDescriptors.options,
140
+ value: [
141
+ {
142
+ contexts,
143
+ },
144
+ ],
145
+ },
146
+ },
147
+ );
148
+ },
149
+ nonGlobalSettings: true,
150
+ });
151
+ };
152
+
69
153
  /* eslint-disable jsdoc/valid-types -- Bug */
70
154
  /**
71
155
  * @typedef {"recommended" | "stylistic" | "contents" | "logical" | "requirements"} ConfigGroups
@@ -117,6 +201,16 @@ index.rules = {
117
201
  'require-file-overview': requireFileOverview,
118
202
  'require-hyphen-before-param-description': requireHyphenBeforeParamDescription,
119
203
  'require-jsdoc': requireJsdoc,
204
+ 'require-next-type': buildForbidRuleDefinition({
205
+ contexts: [
206
+ {
207
+ comment: 'JsdocBlock:has(JsdocTag[tag=next]:not([parsedType.type]))',
208
+ context: 'any',
209
+ message: '@next should have a type',
210
+ },
211
+ ],
212
+ description: 'Requires a type for @next tags',
213
+ }),
120
214
  'require-param': requireParam,
121
215
  'require-param-description': requireParamDescription,
122
216
  'require-param-name': requireParamName,
@@ -131,8 +225,28 @@ index.rules = {
131
225
  'require-returns-type': requireReturnsType,
132
226
  'require-template': requireTemplate,
133
227
  'require-throws': requireThrows,
228
+ 'require-throws-type': buildForbidRuleDefinition({
229
+ contexts: [
230
+ {
231
+ comment: 'JsdocBlock:has(JsdocTag[tag=throws]:not([parsedType.type]))',
232
+ context: 'any',
233
+ message: '@throws should have a type',
234
+ },
235
+ ],
236
+ description: 'Requires a type for @throws tags',
237
+ }),
134
238
  'require-yields': requireYields,
135
239
  'require-yields-check': requireYieldsCheck,
240
+ 'require-yields-type': buildForbidRuleDefinition({
241
+ contexts: [
242
+ {
243
+ comment: 'JsdocBlock:has(JsdocTag[tag=yields]:not([parsedType.type]))',
244
+ context: 'any',
245
+ message: '@yields should have a type',
246
+ },
247
+ ],
248
+ description: 'Requires a type for @yields tags',
249
+ }),
136
250
  'sort-tags': sortTags,
137
251
  'tag-lines': tagLines,
138
252
  'text-escaping': textEscaping,
@@ -195,6 +309,7 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
195
309
  'jsdoc/require-file-overview': 'off',
196
310
  'jsdoc/require-hyphen-before-param-description': 'off',
197
311
  'jsdoc/require-jsdoc': warnOrError,
312
+ 'jsdoc/require-next-type': warnOrError,
198
313
  'jsdoc/require-param': warnOrError,
199
314
  'jsdoc/require-param-description': warnOrError,
200
315
  'jsdoc/require-param-name': warnOrError,
@@ -209,8 +324,10 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
209
324
  'jsdoc/require-returns-type': warnOrError,
210
325
  'jsdoc/require-template': 'off',
211
326
  'jsdoc/require-throws': 'off',
327
+ 'jsdoc/require-throws-type': warnOrError,
212
328
  'jsdoc/require-yields': warnOrError,
213
329
  'jsdoc/require-yields-check': warnOrError,
330
+ 'jsdoc/require-yields-type': warnOrError,
214
331
  'jsdoc/sort-tags': 'off',
215
332
  'jsdoc/tag-lines': warnOrError,
216
333
  'jsdoc/text-escaping': 'off',
@@ -344,6 +461,7 @@ const createLogicalTypescriptFlavorRuleset = createStandaloneRulesetFactory(logi
344
461
  const requirementsRules = [
345
462
  'jsdoc/require-example',
346
463
  'jsdoc/require-jsdoc',
464
+ 'jsdoc/require-next-type',
347
465
  'jsdoc/require-param',
348
466
  'jsdoc/require-param-description',
349
467
  'jsdoc/require-param-name',
@@ -352,7 +470,9 @@ const requirementsRules = [
352
470
  'jsdoc/require-property-name',
353
471
  'jsdoc/require-returns',
354
472
  'jsdoc/require-returns-description',
473
+ 'jsdoc/require-throws-type',
355
474
  'jsdoc/require-yields',
475
+ 'jsdoc/require-yields-type',
356
476
  ];
357
477
 
358
478
  const createRequirementsTypeScriptRuleset = createStandaloneRulesetFactory(requirementsRules);
@@ -540,10 +660,22 @@ export default index;
540
660
  /**
541
661
  * @type {((
542
662
  * cfg?: import('eslint').Linter.Config & {
543
- * mergeSettings?: boolean,
544
663
  * config?: `flat/${ConfigGroups}${ConfigVariants}${ErrorLevelVariants}`,
664
+ * mergeSettings?: boolean,
545
665
  * 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]>}
666
+ * rules?: {[key in keyof import('./rules.d.ts').Rules]?: import('eslint').Linter.RuleEntry<import('./rules.d.ts').Rules[key]>},
667
+ * extraRuleDefinitions?: {
668
+ * forbid: {
669
+ * [contextName: string]: {
670
+ * description?: string,
671
+ * contexts: (string|{
672
+ * message: string,
673
+ * context: string,
674
+ * comment: string
675
+ * })[]
676
+ * }
677
+ * }
678
+ * }
547
679
  * }
548
680
  * ) => import('eslint').Linter.Config)}
549
681
  */
@@ -611,6 +743,29 @@ export const jsdoc = function (cfg) {
611
743
  if (cfg.processor) {
612
744
  outputConfig.processor = cfg.processor;
613
745
  }
746
+
747
+ if (cfg.extraRuleDefinitions) {
748
+ if (!outputConfig.plugins?.jsdoc?.rules) {
749
+ throw new Error('JSDoc plugin required for `extraRuleDefinitions`');
750
+ }
751
+
752
+ if (cfg.extraRuleDefinitions.forbid) {
753
+ for (const [
754
+ contextName,
755
+ {
756
+ contexts,
757
+ description,
758
+ },
759
+ ] of Object.entries(cfg.extraRuleDefinitions.forbid)) {
760
+ outputConfig.plugins.jsdoc.rules[`forbid-${contextName}`] =
761
+ buildForbidRuleDefinition({
762
+ contextName,
763
+ contexts,
764
+ description,
765
+ });
766
+ }
767
+ }
768
+ }
614
769
  }
615
770
 
616
771
  outputConfig.settings = {
@@ -629,16 +784,6 @@ export const jsdoc = function (cfg) {
629
784
  'type',
630
785
  ],
631
786
  },
632
- throws: {
633
- required: [
634
- 'type',
635
- ],
636
- },
637
- yields: {
638
- required: [
639
- 'type',
640
- ],
641
- },
642
787
  },
643
788
  } :
644
789
  {},