@depup/eslint-plugin-jsdoc 62.8.0-depup.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 (430) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +33 -0
  3. package/changes.json +18 -0
  4. package/dist/WarnSettings.cjs +38 -0
  5. package/dist/WarnSettings.cjs.map +1 -0
  6. package/dist/WarnSettings.d.ts +17 -0
  7. package/dist/alignTransform.cjs +402 -0
  8. package/dist/alignTransform.cjs.map +1 -0
  9. package/dist/alignTransform.d.ts +34 -0
  10. package/dist/buildForbidRuleDefinition.cjs +101 -0
  11. package/dist/buildForbidRuleDefinition.cjs.map +1 -0
  12. package/dist/buildForbidRuleDefinition.d.ts +15 -0
  13. package/dist/buildRejectOrPreferRuleDefinition.cjs +352 -0
  14. package/dist/buildRejectOrPreferRuleDefinition.cjs.map +1 -0
  15. package/dist/buildRejectOrPreferRuleDefinition.d.ts +9 -0
  16. package/dist/cjs/WarnSettings.d.ts +16 -0
  17. package/dist/cjs/alignTransform.d.ts +33 -0
  18. package/dist/cjs/buildForbidRuleDefinition.d.ts +14 -0
  19. package/dist/cjs/buildRejectOrPreferRuleDefinition.d.ts +8 -0
  20. package/dist/cjs/defaultTagOrder.d.ts +4 -0
  21. package/dist/cjs/exportParser.d.ts +40 -0
  22. package/dist/cjs/getDefaultTagStructureForMode.d.ts +10 -0
  23. package/dist/cjs/getJsdocProcessorPlugin.d.cts +5 -0
  24. package/dist/cjs/getJsdocProcessorPlugin.d.ts +66 -0
  25. package/dist/cjs/index-cjs.d.ts +23 -0
  26. package/dist/cjs/index.cjs.d.cts +2 -0
  27. package/dist/cjs/iterateJsdoc.d.cts +7 -0
  28. package/dist/cjs/iterateJsdoc.d.ts +495 -0
  29. package/dist/cjs/jsdocUtils.d.ts +493 -0
  30. package/dist/cjs/rules/checkAccess.d.ts +2 -0
  31. package/dist/cjs/rules/checkAlignment.d.ts +2 -0
  32. package/dist/cjs/rules/checkExamples.d.ts +3 -0
  33. package/dist/cjs/rules/checkIndentation.d.ts +2 -0
  34. package/dist/cjs/rules/checkLineAlignment.d.ts +9 -0
  35. package/dist/cjs/rules/checkParamNames.d.ts +2 -0
  36. package/dist/cjs/rules/checkPropertyNames.d.ts +2 -0
  37. package/dist/cjs/rules/checkSyntax.d.ts +2 -0
  38. package/dist/cjs/rules/checkTagNames.d.ts +2 -0
  39. package/dist/cjs/rules/checkTemplateNames.d.ts +2 -0
  40. package/dist/cjs/rules/checkTypes.d.ts +7 -0
  41. package/dist/cjs/rules/checkValues.d.ts +2 -0
  42. package/dist/cjs/rules/convertToJsdocComments.d.ts +266 -0
  43. package/dist/cjs/rules/emptyTags.d.ts +2 -0
  44. package/dist/cjs/rules/escapeInlineTags.d.ts +2 -0
  45. package/dist/cjs/rules/implementsOnClasses.d.ts +2 -0
  46. package/dist/cjs/rules/importsAsDependencies.d.ts +2 -0
  47. package/dist/cjs/rules/informativeDocs.d.ts +2 -0
  48. package/dist/cjs/rules/linesBeforeBlock.d.ts +2 -0
  49. package/dist/cjs/rules/matchDescription.d.ts +2 -0
  50. package/dist/cjs/rules/matchName.d.ts +2 -0
  51. package/dist/cjs/rules/multilineBlocks.d.ts +2 -0
  52. package/dist/cjs/rules/noBadBlocks.d.ts +2 -0
  53. package/dist/cjs/rules/noBlankBlockDescriptions.d.ts +2 -0
  54. package/dist/cjs/rules/noBlankBlocks.d.ts +2 -0
  55. package/dist/cjs/rules/noDefaults.d.ts +2 -0
  56. package/dist/cjs/rules/noMissingSyntax.d.ts +9 -0
  57. package/dist/cjs/rules/noMultiAsterisks.d.ts +2 -0
  58. package/dist/cjs/rules/noRestrictedSyntax.d.ts +2 -0
  59. package/dist/cjs/rules/noTypes.d.ts +2 -0
  60. package/dist/cjs/rules/noUndefinedTypes.d.ts +2 -0
  61. package/dist/cjs/rules/preferImportTag.d.ts +2 -0
  62. package/dist/cjs/rules/requireAsteriskPrefix.d.ts +2 -0
  63. package/dist/cjs/rules/requireDescription.d.ts +2 -0
  64. package/dist/cjs/rules/requireDescriptionCompleteSentence.d.ts +2 -0
  65. package/dist/cjs/rules/requireExample.d.ts +2 -0
  66. package/dist/cjs/rules/requireFileOverview.d.ts +2 -0
  67. package/dist/cjs/rules/requireHyphenBeforeParamDescription.d.ts +2 -0
  68. package/dist/cjs/rules/requireJsdoc.d.ts +24 -0
  69. package/dist/cjs/rules/requireParam.d.ts +3 -0
  70. package/dist/cjs/rules/requireParamDescription.d.ts +2 -0
  71. package/dist/cjs/rules/requireParamName.d.ts +2 -0
  72. package/dist/cjs/rules/requireParamType.d.ts +2 -0
  73. package/dist/cjs/rules/requireProperty.d.ts +2 -0
  74. package/dist/cjs/rules/requirePropertyDescription.d.ts +2 -0
  75. package/dist/cjs/rules/requirePropertyName.d.ts +2 -0
  76. package/dist/cjs/rules/requirePropertyType.d.ts +2 -0
  77. package/dist/cjs/rules/requireRejects.d.ts +2 -0
  78. package/dist/cjs/rules/requireReturns.d.ts +2 -0
  79. package/dist/cjs/rules/requireReturnsCheck.d.ts +2 -0
  80. package/dist/cjs/rules/requireReturnsDescription.d.ts +2 -0
  81. package/dist/cjs/rules/requireReturnsType.d.ts +2 -0
  82. package/dist/cjs/rules/requireTags.d.ts +2 -0
  83. package/dist/cjs/rules/requireTemplate.d.ts +2 -0
  84. package/dist/cjs/rules/requireThrows.d.ts +2 -0
  85. package/dist/cjs/rules/requireYields.d.ts +2 -0
  86. package/dist/cjs/rules/requireYieldsCheck.d.ts +2 -0
  87. package/dist/cjs/rules/sortTags.d.ts +2 -0
  88. package/dist/cjs/rules/tagLines.d.ts +2 -0
  89. package/dist/cjs/rules/textEscaping.d.ts +2 -0
  90. package/dist/cjs/rules/tsMethodSignatureStyle.d.ts +2 -0
  91. package/dist/cjs/rules/tsNoEmptyObjectType.d.ts +2 -0
  92. package/dist/cjs/rules/tsNoUnnecessaryTemplateExpression.d.ts +2 -0
  93. package/dist/cjs/rules/tsPreferFunctionType.d.ts +2 -0
  94. package/dist/cjs/rules/typeFormatting.d.ts +2 -0
  95. package/dist/cjs/rules/validTypes.d.ts +2 -0
  96. package/dist/cjs/tagNames.d.ts +15 -0
  97. package/dist/cjs/utils/hasReturnValue.d.ts +19 -0
  98. package/dist/defaultTagOrder.cjs +46 -0
  99. package/dist/defaultTagOrder.cjs.map +1 -0
  100. package/dist/defaultTagOrder.d.ts +5 -0
  101. package/dist/exportParser.cjs +732 -0
  102. package/dist/exportParser.cjs.map +1 -0
  103. package/dist/exportParser.d.ts +41 -0
  104. package/dist/generateDocs.cjs +342 -0
  105. package/dist/generateDocs.cjs.map +1 -0
  106. package/dist/generateOptions.cjs +62 -0
  107. package/dist/generateOptions.cjs.map +1 -0
  108. package/dist/generateRule.cjs +248 -0
  109. package/dist/generateRule.cjs.map +1 -0
  110. package/dist/generateRuleTypes.cjs +24 -0
  111. package/dist/generateRuleTypes.cjs.map +1 -0
  112. package/dist/getDefaultTagStructureForMode.cjs +289 -0
  113. package/dist/getDefaultTagStructureForMode.cjs.map +1 -0
  114. package/dist/getDefaultTagStructureForMode.d.ts +11 -0
  115. package/dist/getJsdocProcessorPlugin.cjs +587 -0
  116. package/dist/getJsdocProcessorPlugin.cjs.map +1 -0
  117. package/dist/getJsdocProcessorPlugin.cts +5 -0
  118. package/dist/getJsdocProcessorPlugin.d.ts +67 -0
  119. package/dist/index-cjs.cjs +595 -0
  120. package/dist/index-cjs.cjs.map +1 -0
  121. package/dist/index-cjs.d.ts +24 -0
  122. package/dist/index-esm.cjs +162 -0
  123. package/dist/index-esm.cjs.map +1 -0
  124. package/dist/index-esm.d.ts +72 -0
  125. package/dist/index.cjs +743 -0
  126. package/dist/index.cjs.cts +3 -0
  127. package/dist/index.cjs.map +1 -0
  128. package/dist/index.d.ts +93 -0
  129. package/dist/iterateJsdoc.cjs +2150 -0
  130. package/dist/iterateJsdoc.cjs.map +1 -0
  131. package/dist/iterateJsdoc.cts +7 -0
  132. package/dist/iterateJsdoc.d.ts +496 -0
  133. package/dist/jsdocUtils.cjs +1725 -0
  134. package/dist/jsdocUtils.cjs.map +1 -0
  135. package/dist/jsdocUtils.d.ts +494 -0
  136. package/dist/rules/checkAccess.cjs +40 -0
  137. package/dist/rules/checkAccess.cjs.map +1 -0
  138. package/dist/rules/checkAccess.d.ts +3 -0
  139. package/dist/rules/checkAlignment.cjs +78 -0
  140. package/dist/rules/checkAlignment.cjs.map +1 -0
  141. package/dist/rules/checkAlignment.d.ts +3 -0
  142. package/dist/rules/checkExamples.cjs +521 -0
  143. package/dist/rules/checkExamples.cjs.map +1 -0
  144. package/dist/rules/checkExamples.d.ts +4 -0
  145. package/dist/rules/checkIndentation.cjs +170 -0
  146. package/dist/rules/checkIndentation.cjs.map +1 -0
  147. package/dist/rules/checkIndentation.d.ts +3 -0
  148. package/dist/rules/checkLineAlignment.cjs +398 -0
  149. package/dist/rules/checkLineAlignment.cjs.map +1 -0
  150. package/dist/rules/checkLineAlignment.d.ts +10 -0
  151. package/dist/rules/checkParamNames.cjs +407 -0
  152. package/dist/rules/checkParamNames.cjs.map +1 -0
  153. package/dist/rules/checkParamNames.d.ts +3 -0
  154. package/dist/rules/checkPropertyNames.cjs +135 -0
  155. package/dist/rules/checkPropertyNames.cjs.map +1 -0
  156. package/dist/rules/checkPropertyNames.d.ts +3 -0
  157. package/dist/rules/checkSyntax.cjs +38 -0
  158. package/dist/rules/checkSyntax.cjs.map +1 -0
  159. package/dist/rules/checkSyntax.d.ts +3 -0
  160. package/dist/rules/checkTagNames.cjs +312 -0
  161. package/dist/rules/checkTagNames.cjs.map +1 -0
  162. package/dist/rules/checkTagNames.d.ts +3 -0
  163. package/dist/rules/checkTemplateNames.cjs +185 -0
  164. package/dist/rules/checkTemplateNames.cjs.map +1 -0
  165. package/dist/rules/checkTemplateNames.d.ts +3 -0
  166. package/dist/rules/checkTypes.cjs +111 -0
  167. package/dist/rules/checkTypes.cjs.map +1 -0
  168. package/dist/rules/checkTypes.d.ts +8 -0
  169. package/dist/rules/checkValues.cjs +166 -0
  170. package/dist/rules/checkValues.cjs.map +1 -0
  171. package/dist/rules/checkValues.d.ts +3 -0
  172. package/dist/rules/convertToJsdocComments.cjs +356 -0
  173. package/dist/rules/convertToJsdocComments.cjs.map +1 -0
  174. package/dist/rules/convertToJsdocComments.d.ts +267 -0
  175. package/dist/rules/emptyTags.cjs +85 -0
  176. package/dist/rules/emptyTags.cjs.map +1 -0
  177. package/dist/rules/emptyTags.d.ts +3 -0
  178. package/dist/rules/escapeInlineTags.cjs +149 -0
  179. package/dist/rules/escapeInlineTags.cjs.map +1 -0
  180. package/dist/rules/escapeInlineTags.d.ts +3 -0
  181. package/dist/rules/implementsOnClasses.cjs +74 -0
  182. package/dist/rules/implementsOnClasses.cjs.map +1 -0
  183. package/dist/rules/implementsOnClasses.d.ts +3 -0
  184. package/dist/rules/importsAsDependencies.cjs +104 -0
  185. package/dist/rules/importsAsDependencies.cjs.map +1 -0
  186. package/dist/rules/importsAsDependencies.d.ts +3 -0
  187. package/dist/rules/informativeDocs.cjs +187 -0
  188. package/dist/rules/informativeDocs.cjs.map +1 -0
  189. package/dist/rules/informativeDocs.d.ts +3 -0
  190. package/dist/rules/linesBeforeBlock.cjs +120 -0
  191. package/dist/rules/linesBeforeBlock.cjs.map +1 -0
  192. package/dist/rules/linesBeforeBlock.d.ts +3 -0
  193. package/dist/rules/matchDescription.cjs +356 -0
  194. package/dist/rules/matchDescription.cjs.map +1 -0
  195. package/dist/rules/matchDescription.d.ts +3 -0
  196. package/dist/rules/matchName.cjs +160 -0
  197. package/dist/rules/matchName.cjs.map +1 -0
  198. package/dist/rules/matchName.d.ts +3 -0
  199. package/dist/rules/multilineBlocks.cjs +431 -0
  200. package/dist/rules/multilineBlocks.cjs.map +1 -0
  201. package/dist/rules/multilineBlocks.d.ts +3 -0
  202. package/dist/rules/noBadBlocks.cjs +100 -0
  203. package/dist/rules/noBadBlocks.cjs.map +1 -0
  204. package/dist/rules/noBadBlocks.d.ts +3 -0
  205. package/dist/rules/noBlankBlockDescriptions.cjs +63 -0
  206. package/dist/rules/noBlankBlockDescriptions.cjs.map +1 -0
  207. package/dist/rules/noBlankBlockDescriptions.d.ts +3 -0
  208. package/dist/rules/noBlankBlocks.cjs +54 -0
  209. package/dist/rules/noBlankBlocks.cjs.map +1 -0
  210. package/dist/rules/noBlankBlocks.d.ts +3 -0
  211. package/dist/rules/noDefaults.cjs +102 -0
  212. package/dist/rules/noDefaults.cjs.map +1 -0
  213. package/dist/rules/noDefaults.d.ts +3 -0
  214. package/dist/rules/noMissingSyntax.cjs +196 -0
  215. package/dist/rules/noMissingSyntax.cjs.map +1 -0
  216. package/dist/rules/noMissingSyntax.d.ts +10 -0
  217. package/dist/rules/noMultiAsterisks.cjs +126 -0
  218. package/dist/rules/noMultiAsterisks.cjs.map +1 -0
  219. package/dist/rules/noMultiAsterisks.d.ts +3 -0
  220. package/dist/rules/noRestrictedSyntax.cjs +68 -0
  221. package/dist/rules/noRestrictedSyntax.cjs.map +1 -0
  222. package/dist/rules/noRestrictedSyntax.d.ts +3 -0
  223. package/dist/rules/noTypes.cjs +101 -0
  224. package/dist/rules/noTypes.cjs.map +1 -0
  225. package/dist/rules/noTypes.d.ts +3 -0
  226. package/dist/rules/noUndefinedTypes.cjs +588 -0
  227. package/dist/rules/noUndefinedTypes.cjs.map +1 -0
  228. package/dist/rules/noUndefinedTypes.d.ts +3 -0
  229. package/dist/rules/preferImportTag.cjs +362 -0
  230. package/dist/rules/preferImportTag.cjs.map +1 -0
  231. package/dist/rules/preferImportTag.d.ts +3 -0
  232. package/dist/rules/requireAsteriskPrefix.cjs +190 -0
  233. package/dist/rules/requireAsteriskPrefix.cjs.map +1 -0
  234. package/dist/rules/requireAsteriskPrefix.d.ts +3 -0
  235. package/dist/rules/requireDescription.cjs +164 -0
  236. package/dist/rules/requireDescription.cjs.map +1 -0
  237. package/dist/rules/requireDescription.d.ts +3 -0
  238. package/dist/rules/requireDescriptionCompleteSentence.cjs +321 -0
  239. package/dist/rules/requireDescriptionCompleteSentence.cjs.map +1 -0
  240. package/dist/rules/requireDescriptionCompleteSentence.d.ts +3 -0
  241. package/dist/rules/requireExample.cjs +133 -0
  242. package/dist/rules/requireExample.cjs.map +1 -0
  243. package/dist/rules/requireExample.d.ts +3 -0
  244. package/dist/rules/requireFileOverview.cjs +194 -0
  245. package/dist/rules/requireFileOverview.cjs.map +1 -0
  246. package/dist/rules/requireFileOverview.d.ts +3 -0
  247. package/dist/rules/requireHyphenBeforeParamDescription.cjs +166 -0
  248. package/dist/rules/requireHyphenBeforeParamDescription.cjs.map +1 -0
  249. package/dist/rules/requireHyphenBeforeParamDescription.d.ts +3 -0
  250. package/dist/rules/requireJsdoc.cjs +722 -0
  251. package/dist/rules/requireJsdoc.cjs.map +1 -0
  252. package/dist/rules/requireJsdoc.d.ts +25 -0
  253. package/dist/rules/requireParam.cjs +772 -0
  254. package/dist/rules/requireParam.cjs.map +1 -0
  255. package/dist/rules/requireParam.d.ts +4 -0
  256. package/dist/rules/requireParamDescription.cjs +105 -0
  257. package/dist/rules/requireParamDescription.cjs.map +1 -0
  258. package/dist/rules/requireParamDescription.d.ts +3 -0
  259. package/dist/rules/requireParamName.cjs +68 -0
  260. package/dist/rules/requireParamName.cjs.map +1 -0
  261. package/dist/rules/requireParamName.d.ts +3 -0
  262. package/dist/rules/requireParamType.cjs +104 -0
  263. package/dist/rules/requireParamType.cjs.map +1 -0
  264. package/dist/rules/requireParamType.d.ts +3 -0
  265. package/dist/rules/requireProperty.cjs +63 -0
  266. package/dist/rules/requireProperty.cjs.map +1 -0
  267. package/dist/rules/requireProperty.d.ts +3 -0
  268. package/dist/rules/requirePropertyDescription.cjs +29 -0
  269. package/dist/rules/requirePropertyDescription.cjs.map +1 -0
  270. package/dist/rules/requirePropertyDescription.d.ts +3 -0
  271. package/dist/rules/requirePropertyName.cjs +29 -0
  272. package/dist/rules/requirePropertyName.cjs.map +1 -0
  273. package/dist/rules/requirePropertyName.d.ts +3 -0
  274. package/dist/rules/requirePropertyType.cjs +29 -0
  275. package/dist/rules/requirePropertyType.cjs.map +1 -0
  276. package/dist/rules/requirePropertyType.d.ts +3 -0
  277. package/dist/rules/requireRejects.cjs +226 -0
  278. package/dist/rules/requireRejects.cjs.map +1 -0
  279. package/dist/rules/requireRejects.d.ts +3 -0
  280. package/dist/rules/requireReturns.cjs +262 -0
  281. package/dist/rules/requireReturns.cjs.map +1 -0
  282. package/dist/rules/requireReturns.d.ts +3 -0
  283. package/dist/rules/requireReturnsCheck.cjs +140 -0
  284. package/dist/rules/requireReturnsCheck.cjs.map +1 -0
  285. package/dist/rules/requireReturnsCheck.d.ts +3 -0
  286. package/dist/rules/requireReturnsDescription.cjs +72 -0
  287. package/dist/rules/requireReturnsDescription.cjs.map +1 -0
  288. package/dist/rules/requireReturnsDescription.d.ts +3 -0
  289. package/dist/rules/requireReturnsType.cjs +68 -0
  290. package/dist/rules/requireReturnsType.cjs.map +1 -0
  291. package/dist/rules/requireReturnsType.d.ts +3 -0
  292. package/dist/rules/requireTags.cjs +74 -0
  293. package/dist/rules/requireTags.cjs.map +1 -0
  294. package/dist/rules/requireTags.d.ts +3 -0
  295. package/dist/rules/requireTemplate.cjs +220 -0
  296. package/dist/rules/requireTemplate.cjs.map +1 -0
  297. package/dist/rules/requireTemplate.d.ts +3 -0
  298. package/dist/rules/requireThrows.cjs +118 -0
  299. package/dist/rules/requireThrows.cjs.map +1 -0
  300. package/dist/rules/requireThrows.d.ts +3 -0
  301. package/dist/rules/requireYields.cjs +224 -0
  302. package/dist/rules/requireYields.cjs.map +1 -0
  303. package/dist/rules/requireYields.d.ts +3 -0
  304. package/dist/rules/requireYieldsCheck.cjs +179 -0
  305. package/dist/rules/requireYieldsCheck.cjs.map +1 -0
  306. package/dist/rules/requireYieldsCheck.d.ts +3 -0
  307. package/dist/rules/sortTags.cjs +656 -0
  308. package/dist/rules/sortTags.cjs.map +1 -0
  309. package/dist/rules/sortTags.d.ts +3 -0
  310. package/dist/rules/tagLines.cjs +374 -0
  311. package/dist/rules/tagLines.cjs.map +1 -0
  312. package/dist/rules/tagLines.d.ts +3 -0
  313. package/dist/rules/textEscaping.cjs +141 -0
  314. package/dist/rules/textEscaping.cjs.map +1 -0
  315. package/dist/rules/textEscaping.d.ts +3 -0
  316. package/dist/rules/tsMethodSignatureStyle.cjs +240 -0
  317. package/dist/rules/tsMethodSignatureStyle.cjs.map +1 -0
  318. package/dist/rules/tsMethodSignatureStyle.d.ts +3 -0
  319. package/dist/rules/tsNoEmptyObjectType.cjs +62 -0
  320. package/dist/rules/tsNoEmptyObjectType.cjs.map +1 -0
  321. package/dist/rules/tsNoEmptyObjectType.d.ts +3 -0
  322. package/dist/rules/tsNoUnnecessaryTemplateExpression.cjs +104 -0
  323. package/dist/rules/tsNoUnnecessaryTemplateExpression.cjs.map +1 -0
  324. package/dist/rules/tsNoUnnecessaryTemplateExpression.d.ts +3 -0
  325. package/dist/rules/tsPreferFunctionType.cjs +110 -0
  326. package/dist/rules/tsPreferFunctionType.cjs.map +1 -0
  327. package/dist/rules/tsPreferFunctionType.d.ts +3 -0
  328. package/dist/rules/typeFormatting.cjs +607 -0
  329. package/dist/rules/typeFormatting.cjs.map +1 -0
  330. package/dist/rules/typeFormatting.d.ts +3 -0
  331. package/dist/rules/validTypes.cjs +328 -0
  332. package/dist/rules/validTypes.cjs.map +1 -0
  333. package/dist/rules/validTypes.d.ts +3 -0
  334. package/dist/rules.d.ts +3203 -0
  335. package/dist/tagNames.cjs +244 -0
  336. package/dist/tagNames.cjs.map +1 -0
  337. package/dist/tagNames.d.ts +16 -0
  338. package/dist/to-valid-identifier.cjs +263 -0
  339. package/dist/utils/hasReturnValue.cjs +495 -0
  340. package/dist/utils/hasReturnValue.cjs.map +1 -0
  341. package/dist/utils/hasReturnValue.d.ts +20 -0
  342. package/package.json +220 -0
  343. package/rollup.config.js +16 -0
  344. package/src/WarnSettings.js +34 -0
  345. package/src/alignTransform.js +444 -0
  346. package/src/buildForbidRuleDefinition.js +106 -0
  347. package/src/buildRejectOrPreferRuleDefinition.js +481 -0
  348. package/src/defaultTagOrder.js +169 -0
  349. package/src/exportParser.js +973 -0
  350. package/src/getDefaultTagStructureForMode.js +968 -0
  351. package/src/getJsdocProcessorPlugin.cts +5 -0
  352. package/src/getJsdocProcessorPlugin.js +692 -0
  353. package/src/index-cjs.js +755 -0
  354. package/src/index-esm.js +196 -0
  355. package/src/index.cjs.cts +3 -0
  356. package/src/index.js +940 -0
  357. package/src/iterateJsdoc.cts +7 -0
  358. package/src/iterateJsdoc.js +2612 -0
  359. package/src/jsdocUtils.js +2158 -0
  360. package/src/rules/checkAccess.js +45 -0
  361. package/src/rules/checkAlignment.js +82 -0
  362. package/src/rules/checkExamples.js +613 -0
  363. package/src/rules/checkIndentation.js +176 -0
  364. package/src/rules/checkLineAlignment.js +453 -0
  365. package/src/rules/checkParamNames.js +541 -0
  366. package/src/rules/checkPropertyNames.js +174 -0
  367. package/src/rules/checkSyntax.js +30 -0
  368. package/src/rules/checkTagNames.js +414 -0
  369. package/src/rules/checkTemplateNames.js +208 -0
  370. package/src/rules/checkTypes.js +130 -0
  371. package/src/rules/checkValues.js +264 -0
  372. package/src/rules/convertToJsdocComments.js +444 -0
  373. package/src/rules/emptyTags.js +106 -0
  374. package/src/rules/escapeInlineTags.js +189 -0
  375. package/src/rules/implementsOnClasses.js +78 -0
  376. package/src/rules/importsAsDependencies.js +132 -0
  377. package/src/rules/informativeDocs.js +228 -0
  378. package/src/rules/linesBeforeBlock.js +144 -0
  379. package/src/rules/matchDescription.js +413 -0
  380. package/src/rules/matchName.js +179 -0
  381. package/src/rules/multilineBlocks.js +562 -0
  382. package/src/rules/noBadBlocks.js +127 -0
  383. package/src/rules/noBlankBlockDescriptions.js +69 -0
  384. package/src/rules/noBlankBlocks.js +55 -0
  385. package/src/rules/noDefaults.js +104 -0
  386. package/src/rules/noMissingSyntax.js +215 -0
  387. package/src/rules/noMultiAsterisks.js +162 -0
  388. package/src/rules/noRestrictedSyntax.js +72 -0
  389. package/src/rules/noTypes.js +108 -0
  390. package/src/rules/noUndefinedTypes.js +797 -0
  391. package/src/rules/preferImportTag.js +521 -0
  392. package/src/rules/requireAsteriskPrefix.js +217 -0
  393. package/src/rules/requireDescription.js +190 -0
  394. package/src/rules/requireDescriptionCompleteSentence.js +376 -0
  395. package/src/rules/requireExample.js +143 -0
  396. package/src/rules/requireFileOverview.js +213 -0
  397. package/src/rules/requireHyphenBeforeParamDescription.js +210 -0
  398. package/src/rules/requireJsdoc.js +897 -0
  399. package/src/rules/requireParam.js +848 -0
  400. package/src/rules/requireParamDescription.js +110 -0
  401. package/src/rules/requireParamName.js +69 -0
  402. package/src/rules/requireParamType.js +109 -0
  403. package/src/rules/requireProperty.js +66 -0
  404. package/src/rules/requirePropertyDescription.js +25 -0
  405. package/src/rules/requirePropertyName.js +25 -0
  406. package/src/rules/requirePropertyType.js +25 -0
  407. package/src/rules/requireRejects.js +246 -0
  408. package/src/rules/requireReturns.js +291 -0
  409. package/src/rules/requireReturnsCheck.js +180 -0
  410. package/src/rules/requireReturnsDescription.js +73 -0
  411. package/src/rules/requireReturnsType.js +65 -0
  412. package/src/rules/requireTags.js +85 -0
  413. package/src/rules/requireTemplate.js +246 -0
  414. package/src/rules/requireThrows.js +128 -0
  415. package/src/rules/requireYields.js +265 -0
  416. package/src/rules/requireYieldsCheck.js +226 -0
  417. package/src/rules/sortTags.js +766 -0
  418. package/src/rules/tagLines.js +486 -0
  419. package/src/rules/textEscaping.js +158 -0
  420. package/src/rules/tsMethodSignatureStyle.js +300 -0
  421. package/src/rules/tsNoEmptyObjectType.js +61 -0
  422. package/src/rules/tsNoUnnecessaryTemplateExpression.js +130 -0
  423. package/src/rules/tsPreferFunctionType.js +127 -0
  424. package/src/rules/typeFormatting.js +690 -0
  425. package/src/rules/validTypes.js +466 -0
  426. package/src/rules.d.ts +3203 -0
  427. package/src/tagNames.js +301 -0
  428. package/src/utils/hasReturnValue.js +572 -0
  429. package/typings/babel__eslint-parser.d.ts +1 -0
  430. package/typings/gitdown.d.ts +16 -0
@@ -0,0 +1,2612 @@
1
+ import * as jsdocUtils from './jsdocUtils.js';
2
+ import {
3
+ commentHandler,
4
+ getJSDocComment,
5
+ parseComment,
6
+ } from '@es-joy/jsdoccomment';
7
+ import {
8
+ stringify as commentStringify,
9
+ util,
10
+ } from 'comment-parser';
11
+ import esquery from 'esquery';
12
+
13
+ /**
14
+ * @typedef {number} Integer
15
+ */
16
+
17
+ /**
18
+ * @typedef {import('@es-joy/jsdoccomment').JsdocBlockWithInline} JsdocBlockWithInline
19
+ */
20
+
21
+ /**
22
+ * @typedef {{
23
+ * disallowName?: string,
24
+ * allowName?: string,
25
+ * context?: string,
26
+ * comment?: string,
27
+ * tags?: string[],
28
+ * replacement?: string,
29
+ * minimum?: Integer,
30
+ * message?: string,
31
+ * forceRequireReturn?: boolean
32
+ * }} ContextObject
33
+ */
34
+ /**
35
+ * @typedef {string|ContextObject} Context
36
+ */
37
+
38
+ /**
39
+ * @callback CheckJsdoc
40
+ * @param {{
41
+ * lastIndex?: Integer,
42
+ * isFunctionContext?: boolean,
43
+ * selector?: string,
44
+ * comment?: string
45
+ * }} info
46
+ * @param {null|((jsdoc: import('@es-joy/jsdoccomment').JsdocBlockWithInline) => boolean|undefined)} handler
47
+ * @param {import('eslint').Rule.Node} node
48
+ * @returns {void}
49
+ */
50
+
51
+ /**
52
+ * @callback ForEachPreferredTag
53
+ * @param {string} tagName
54
+ * @param {(
55
+ * matchingJsdocTag: import('@es-joy/jsdoccomment').JsdocTagWithInline,
56
+ * targetTagName: string
57
+ * ) => void} arrayHandler
58
+ * @param {boolean} [skipReportingBlockedTag]
59
+ * @returns {void}
60
+ */
61
+
62
+ /**
63
+ * @callback ReportSettings
64
+ * @param {string} message
65
+ * @returns {void}
66
+ */
67
+
68
+ /**
69
+ * @callback ParseClosureTemplateTag
70
+ * @param {import('comment-parser').Spec} tag
71
+ * @returns {string[]}
72
+ */
73
+
74
+ /**
75
+ * @callback GetPreferredTagNameObject
76
+ * @param {{
77
+ * tagName: string
78
+ * }} cfg
79
+ * @returns {string|false|{
80
+ * message: string;
81
+ * replacement?: string|undefined
82
+ * }|{
83
+ * blocked: true,
84
+ * tagName: string
85
+ * }}
86
+ */
87
+
88
+ /**
89
+ * @typedef {{
90
+ * forEachPreferredTag: ForEachPreferredTag,
91
+ * reportSettings: ReportSettings,
92
+ * parseClosureTemplateTag: ParseClosureTemplateTag,
93
+ * getPreferredTagNameObject: GetPreferredTagNameObject,
94
+ * pathDoesNotBeginWith: import('./jsdocUtils.js').PathDoesNotBeginWith
95
+ * isNameOrNamepathDefiningTag: IsNamepathX,
96
+ * isNamepathReferencingTag: IsNamepathX,
97
+ * isNamepathOrUrlReferencingTag: IsNamepathX,
98
+ * tagMightHaveNameOrNamepath: IsNamepathX,
99
+ * tagMightHaveName: IsNamepathX
100
+ * }} BasicUtils
101
+ */
102
+
103
+ /**
104
+ * @callback IsIteratingFunction
105
+ * @returns {boolean}
106
+ */
107
+
108
+ /**
109
+ * @callback IsVirtualFunction
110
+ * @returns {boolean}
111
+ */
112
+
113
+ /**
114
+ * @callback Stringify
115
+ * @param {import('comment-parser').Block} tagBlock
116
+ * @param {boolean} [specRewire]
117
+ * @returns {string}
118
+ */
119
+
120
+ /**
121
+ * @callback ReportJSDoc
122
+ * @param {string} msg
123
+ * @param {null|import('comment-parser').Spec|{line: Integer, column?: Integer}} [tag]
124
+ * @param {((fixer: import('eslint').Rule.RuleFixer) => import('eslint').Rule.Fix|void)|null} [handler]
125
+ * @param {boolean} [specRewire]
126
+ * @param {undefined|{
127
+ * [key: string]: string
128
+ * }} [data]
129
+ */
130
+
131
+ /**
132
+ * @callback GetRegexFromString
133
+ * @param {string} str
134
+ * @param {string} [requiredFlags]
135
+ * @returns {RegExp}
136
+ */
137
+
138
+ /**
139
+ * @callback GetTagDescription
140
+ * @param {import('comment-parser').Spec} tg
141
+ * @param {boolean} [returnArray]
142
+ * @returns {string[]|string}
143
+ */
144
+
145
+ /**
146
+ * @callback SetTagDescription
147
+ * @param {import('comment-parser').Spec} tg
148
+ * @param {RegExp} matcher
149
+ * @param {(description: string) => string} setter
150
+ * @returns {Integer}
151
+ */
152
+
153
+ /**
154
+ * @callback GetDescription
155
+ * @returns {{
156
+ * description: string,
157
+ * descriptions: string[],
158
+ * lastDescriptionLine: Integer
159
+ * }}
160
+ */
161
+
162
+ /**
163
+ * @callback SetBlockDescription
164
+ * @param {(
165
+ * info: {
166
+ * delimiter: string,
167
+ * postDelimiter: string,
168
+ * start: string
169
+ * },
170
+ * seedTokens: (
171
+ * tokens?: Partial<import('comment-parser').Tokens>
172
+ * ) => import('comment-parser').Tokens,
173
+ * descLines: string[],
174
+ * postDelims: string[]
175
+ * ) => import('comment-parser').Line[]} setter
176
+ * @returns {void}
177
+ */
178
+
179
+ /**
180
+ * @callback SetDescriptionLines
181
+ * @param {RegExp} matcher
182
+ * @param {(description: string) => string} setter
183
+ * @returns {Integer}
184
+ */
185
+
186
+ /**
187
+ * @callback ChangeTag
188
+ * @param {import('comment-parser').Spec} tag
189
+ * @param {...Partial<import('comment-parser').Tokens>} tokens
190
+ * @returns {void}
191
+ */
192
+
193
+ /**
194
+ * @callback SetTag
195
+ * @param {import('comment-parser').Spec & {
196
+ * line: Integer
197
+ * }} tag
198
+ * @param {Partial<import('comment-parser').Tokens>} [tokens]
199
+ * @returns {void}
200
+ */
201
+
202
+ /**
203
+ * @callback RemoveTag
204
+ * @param {Integer} tagIndex
205
+ * @param {{
206
+ * removeEmptyBlock?: boolean,
207
+ * tagSourceOffset?: Integer
208
+ * }} [cfg]
209
+ * @returns {void}
210
+ */
211
+
212
+ /**
213
+ * @callback AddTag
214
+ * @param {string} targetTagName
215
+ * @param {Integer} [number]
216
+ * @param {Partial<import('comment-parser').Tokens>} [tokens]
217
+ * @returns {void}
218
+ */
219
+
220
+ /**
221
+ * @callback GetFirstLine
222
+ * @returns {Integer|undefined}
223
+ */
224
+
225
+ /**
226
+ * @typedef {(
227
+ * tokens?: Partial<import('comment-parser').Tokens> | undefined
228
+ * ) => import('comment-parser').Tokens} SeedTokens
229
+ */
230
+
231
+ /**
232
+ * Sets tokens to empty string.
233
+ * @callback EmptyTokens
234
+ * @param {import('comment-parser').Tokens} tokens
235
+ * @returns {void}
236
+ */
237
+
238
+ /**
239
+ * @callback AddLine
240
+ * @param {Integer} sourceIndex
241
+ * @param {Partial<import('comment-parser').Tokens>} tokens
242
+ * @returns {void}
243
+ */
244
+
245
+ /**
246
+ * @callback AddLines
247
+ * @param {Integer} tagIndex
248
+ * @param {Integer} tagSourceOffset
249
+ * @param {Integer} numLines
250
+ * @returns {void}
251
+ */
252
+
253
+ /**
254
+ * @callback MakeMultiline
255
+ * @returns {void}
256
+ */
257
+
258
+ /**
259
+ * @callback GetFunctionParameterNames
260
+ * @param {boolean} [useDefaultObjectProperties]
261
+ * @param {boolean} [ignoreInterfacedParameters]
262
+ * @returns {import('./jsdocUtils.js').ParamNameInfo[]}
263
+ */
264
+
265
+ /**
266
+ * @callback HasParams
267
+ * @returns {Integer}
268
+ */
269
+
270
+ /**
271
+ * @callback IsGenerator
272
+ * @returns {boolean}
273
+ */
274
+
275
+ /**
276
+ * @callback IsConstructor
277
+ * @returns {boolean}
278
+ */
279
+
280
+ /**
281
+ * @callback GetJsdocTagsDeep
282
+ * @param {string} tagName
283
+ * @returns {false|{
284
+ * idx: Integer,
285
+ * name: string,
286
+ * type: string
287
+ * }[]}
288
+ */
289
+
290
+ /**
291
+ * @callback GetPreferredTagName
292
+ * @param {{
293
+ * tagName: string,
294
+ * skipReportingBlockedTag?: boolean,
295
+ * allowObjectReturn?: boolean,
296
+ * defaultMessage?: string
297
+ * }} cfg
298
+ * @returns {string|undefined|false|{
299
+ * message: string;
300
+ * replacement?: string|undefined;
301
+ * }|{
302
+ * blocked: true,
303
+ * tagName: string
304
+ * }}
305
+ */
306
+
307
+ /**
308
+ * @callback IsValidTag
309
+ * @param {string} name
310
+ * @param {string[]} definedTags
311
+ * @returns {boolean}
312
+ */
313
+
314
+ /**
315
+ * @callback HasATag
316
+ * @param {string[]} names
317
+ * @returns {boolean}
318
+ */
319
+
320
+ /**
321
+ * @callback HasTag
322
+ * @param {string} name
323
+ * @returns {boolean}
324
+ */
325
+
326
+ /**
327
+ * @callback ComparePaths
328
+ * @param {string} name
329
+ * @returns {(otherPathName: string) => boolean}
330
+ */
331
+
332
+ /**
333
+ * @callback DropPathSegmentQuotes
334
+ * @param {string} name
335
+ * @returns {string}
336
+ */
337
+
338
+ /**
339
+ * @callback AvoidDocs
340
+ * @returns {boolean}
341
+ */
342
+
343
+ /**
344
+ * @callback TagMightHaveNamePositionTypePosition
345
+ * @param {string} tagName
346
+ * @param {import('./getDefaultTagStructureForMode.js').
347
+ * TagStructure[]} [otherModeMaps]
348
+ * @returns {boolean|{otherMode: true}}
349
+ */
350
+
351
+ /**
352
+ * @callback TagMustHave
353
+ * @param {string} tagName
354
+ * @param {import('./getDefaultTagStructureForMode.js').
355
+ * TagStructure[]} otherModeMaps
356
+ * @returns {boolean|{
357
+ * otherMode: false
358
+ * }}
359
+ */
360
+
361
+ /**
362
+ * @callback TagMissingRequiredTypeOrNamepath
363
+ * @param {import('comment-parser').Spec} tag
364
+ * @param {import('./getDefaultTagStructureForMode.js').
365
+ * TagStructure[]} otherModeMaps
366
+ * @returns {boolean|{
367
+ * otherMode: false
368
+ * }}
369
+ */
370
+
371
+ /**
372
+ * @callback IsNamepathX
373
+ * @param {string} tagName
374
+ * @returns {boolean}
375
+ */
376
+
377
+ /**
378
+ * @callback GetTagStructureForMode
379
+ * @param {import('./jsdocUtils.js').ParserMode} mde
380
+ * @returns {import('./getDefaultTagStructureForMode.js').TagStructure}
381
+ */
382
+
383
+ /**
384
+ * @callback MayBeUndefinedTypeTag
385
+ * @param {import('comment-parser').Spec} tag
386
+ * @returns {boolean}
387
+ */
388
+
389
+ /**
390
+ * @callback HasValueOrExecutorHasNonEmptyResolveValue
391
+ * @param {boolean} anyPromiseAsReturn
392
+ * @param {boolean} [allBranches]
393
+ * @returns {boolean}
394
+ */
395
+
396
+ /**
397
+ * @callback HasYieldValue
398
+ * @returns {boolean}
399
+ */
400
+
401
+ /**
402
+ * @callback HasYieldReturnValue
403
+ * @returns {boolean}
404
+ */
405
+
406
+ /**
407
+ * @callback HasThrowValue
408
+ * @returns {boolean}
409
+ */
410
+
411
+ /**
412
+ * @callback IsAsync
413
+ * @returns {boolean|undefined}
414
+ */
415
+
416
+ /**
417
+ * @callback GetTags
418
+ * @param {string} tagName
419
+ * @returns {import('comment-parser').Spec[]}
420
+ */
421
+
422
+ /**
423
+ * @callback GetPresentTags
424
+ * @param {string[]} tagList
425
+ * @returns {import('@es-joy/jsdoccomment').JsdocTagWithInline[]}
426
+ */
427
+
428
+ /**
429
+ * @callback FilterTags
430
+ * @param {(tag: import('@es-joy/jsdoccomment').JsdocTagWithInline) => boolean} filter
431
+ * @returns {import('@es-joy/jsdoccomment').JsdocTagWithInline[]}
432
+ */
433
+
434
+ /**
435
+ * @callback FilterAllTags
436
+ * @param {(tag: (import('comment-parser').Spec|
437
+ * import('@es-joy/jsdoccomment').JsdocInlineTagNoType)) => boolean} filter
438
+ * @returns {(import('comment-parser').Spec|
439
+ * import('@es-joy/jsdoccomment').JsdocInlineTagNoType)[]}
440
+ */
441
+
442
+ /**
443
+ * @callback getInlineTags
444
+ * @returns {(import('comment-parser').Spec|
445
+ * import('@es-joy/jsdoccomment').JsdocInlineTagNoType & {
446
+ * line?: number | undefined; column?: number | undefined;
447
+ * })[]}
448
+ */
449
+
450
+ /**
451
+ * @callback GetTagsByType
452
+ * @param {import('comment-parser').Spec[]} tags
453
+ * @returns {{
454
+ * tagsWithNames: import('comment-parser').Spec[],
455
+ * tagsWithoutNames: import('comment-parser').Spec[]
456
+ * }}
457
+ */
458
+
459
+ /**
460
+ * @callback HasOptionTag
461
+ * @param {string} tagName
462
+ * @returns {boolean}
463
+ */
464
+
465
+ /**
466
+ * @callback GetClassNode
467
+ * @returns {Node|null}
468
+ */
469
+
470
+ /**
471
+ * @callback GetClassJsdoc
472
+ * @returns {null|JsdocBlockWithInline}
473
+ */
474
+
475
+ /**
476
+ * @callback ClassHasTag
477
+ * @param {string} tagName
478
+ * @returns {boolean}
479
+ */
480
+
481
+ /**
482
+ * @callback FindContext
483
+ * @param {Context[]} contexts
484
+ * @param {string|undefined} comment
485
+ * @returns {{
486
+ * foundContext: Context|undefined,
487
+ * contextStr: string
488
+ * }}
489
+ */
490
+
491
+ /**
492
+ * @typedef {BasicUtils & {
493
+ * isIteratingFunction: IsIteratingFunction,
494
+ * isIteratingFunctionOrVariable: IsIteratingFunction,
495
+ * isVirtualFunction: IsVirtualFunction,
496
+ * stringify: Stringify,
497
+ * reportJSDoc: ReportJSDoc,
498
+ * getRegexFromString: GetRegexFromString,
499
+ * getTagDescription: GetTagDescription,
500
+ * setTagDescription: SetTagDescription,
501
+ * getDescription: GetDescription,
502
+ * setBlockDescription: SetBlockDescription,
503
+ * setDescriptionLines: SetDescriptionLines,
504
+ * changeTag: ChangeTag,
505
+ * setTag: SetTag,
506
+ * removeTag: RemoveTag,
507
+ * addTag: AddTag,
508
+ * getFirstLine: GetFirstLine,
509
+ * seedTokens: SeedTokens,
510
+ * emptyTokens: EmptyTokens,
511
+ * addLine: AddLine,
512
+ * addLines: AddLines,
513
+ * makeMultiline: MakeMultiline,
514
+ * flattenRoots: import('./jsdocUtils.js').FlattenRoots,
515
+ * getFunctionParameterNames: GetFunctionParameterNames,
516
+ * hasParams: HasParams,
517
+ * isGenerator: IsGenerator,
518
+ * isConstructor: IsConstructor,
519
+ * getJsdocTagsDeep: GetJsdocTagsDeep,
520
+ * getPreferredTagName: GetPreferredTagName,
521
+ * isValidTag: IsValidTag,
522
+ * hasATag: HasATag,
523
+ * hasTag: HasTag,
524
+ * comparePaths: ComparePaths,
525
+ * dropPathSegmentQuotes: DropPathSegmentQuotes,
526
+ * avoidDocs: AvoidDocs,
527
+ * tagMightHaveNamePosition: TagMightHaveNamePositionTypePosition,
528
+ * tagMightHaveTypePosition: TagMightHaveNamePositionTypePosition,
529
+ * tagMustHaveNamePosition: TagMustHave,
530
+ * tagMustHaveTypePosition: TagMustHave,
531
+ * tagMissingRequiredTypeOrNamepath: TagMissingRequiredTypeOrNamepath,
532
+ * isNameOrNamepathDefiningTag: IsNamepathX,
533
+ * isNamepathReferencingTag: IsNamepathX,
534
+ * isNamepathOrUrlReferencingTag: IsNamepathX,
535
+ * tagMightHaveNameOrNamepath: IsNamepathX,
536
+ * tagMightHaveName: IsNamepathX,
537
+ * tagMightHaveNamepath: IsNamepathX,
538
+ * getTagStructureForMode: GetTagStructureForMode,
539
+ * mayBeUndefinedTypeTag: MayBeUndefinedTypeTag,
540
+ * hasValueOrExecutorHasNonEmptyResolveValue: HasValueOrExecutorHasNonEmptyResolveValue,
541
+ * hasYieldValue: HasYieldValue,
542
+ * hasYieldReturnValue: HasYieldReturnValue,
543
+ * hasThrowValue: HasThrowValue,
544
+ * isAsync: IsAsync,
545
+ * getTags: GetTags,
546
+ * getPresentTags: GetPresentTags,
547
+ * filterTags: FilterTags,
548
+ * filterAllTags: FilterAllTags,
549
+ * getInlineTags: getInlineTags,
550
+ * getTagsByType: GetTagsByType,
551
+ * hasOptionTag: HasOptionTag,
552
+ * getClassNode: GetClassNode,
553
+ * getClassJsdoc: GetClassJsdoc,
554
+ * classHasTag: ClassHasTag,
555
+ * findContext: FindContext
556
+ * }} Utils
557
+ */
558
+
559
+ const {
560
+ rewireSpecs,
561
+ seedTokens,
562
+ } = util;
563
+
564
+ /**
565
+ * Should use ESLint rule's typing.
566
+ * @typedef {import('eslint').Rule.RuleMetaData} EslintRuleMeta
567
+ */
568
+
569
+ /**
570
+ * A plain object for tracking state as needed by rules across iterations.
571
+ * @typedef {{
572
+ * globalTags: boolean,
573
+ * hasDuplicates: {
574
+ * [key: string]: boolean
575
+ * },
576
+ * selectorMap: {
577
+ * [selector: string]: {
578
+ * [comment: string]: Integer
579
+ * }
580
+ * },
581
+ * hasTag: {
582
+ * [key: string]: boolean
583
+ * },
584
+ * hasNonComment: number,
585
+ * hasNonCommentBeforeTag: {
586
+ * [key: string]: boolean|number
587
+ * },
588
+ * foundTypedefValues: string[]
589
+ * }} StateObject
590
+ */
591
+
592
+ /**
593
+ * The Node AST as supplied by the parser.
594
+ * @typedef {import('eslint').Rule.Node} Node
595
+ */
596
+
597
+ /*
598
+ const {
599
+ align as commentAlign,
600
+ flow: commentFlow,
601
+ indent: commentIndent,
602
+ } = transforms;
603
+ */
604
+
605
+ const globalState = new Map();
606
+ /**
607
+ * @param {import('eslint').Rule.RuleContext} context
608
+ * @param {{
609
+ * tagNamePreference?: import('./jsdocUtils.js').TagNamePreference,
610
+ * mode?: import('./jsdocUtils.js').ParserMode
611
+ * }} cfg
612
+ * @returns {BasicUtils}
613
+ */
614
+ const getBasicUtils = (context, {
615
+ mode,
616
+ tagNamePreference,
617
+ }) => {
618
+ /** @type {BasicUtils} */
619
+ const utils = {};
620
+
621
+ for (const method of [
622
+ 'isNameOrNamepathDefiningTag',
623
+ 'isNamepathReferencingTag',
624
+ 'isNamepathOrUrlReferencingTag',
625
+ 'tagMightHaveNameOrNamepath',
626
+ 'tagMightHaveName',
627
+ 'tagMightHaveNamepath',
628
+ ]) {
629
+ /** @type {IsNamepathX} */
630
+ utils[
631
+ /** @type {"isNameOrNamepathDefiningTag"|"isNamepathReferencingTag"|"isNamepathOrUrlReferencingTag"|"tagMightHaveNameOrNamepath"|"tagMightHaveName"} */ (
632
+ method
633
+ )] = (tagName) => {
634
+ return jsdocUtils[
635
+ /** @type {"isNameOrNamepathDefiningTag"|"isNamepathReferencingTag"|"isNamepathOrUrlReferencingTag"|"tagMightHaveNameOrNamepath"|"tagMightHaveName"} */
636
+ (method)
637
+ ](tagName);
638
+ };
639
+ }
640
+
641
+ /** @type {ReportSettings} */
642
+ utils.reportSettings = (message) => {
643
+ context.report({
644
+ loc: {
645
+ end: {
646
+ column: 1,
647
+ line: 1,
648
+ },
649
+ start: {
650
+ column: 1,
651
+ line: 1,
652
+ },
653
+ },
654
+ message,
655
+ });
656
+ };
657
+
658
+ /** @type {ParseClosureTemplateTag} */
659
+ utils.parseClosureTemplateTag = (tag) => {
660
+ return jsdocUtils.parseClosureTemplateTag(tag);
661
+ };
662
+
663
+ utils.pathDoesNotBeginWith = jsdocUtils.pathDoesNotBeginWith;
664
+
665
+ /** @type {GetPreferredTagNameObject} */
666
+ utils.getPreferredTagNameObject = ({
667
+ tagName,
668
+ }) => {
669
+ const ret = jsdocUtils.getPreferredTagNameSimple(
670
+ tagName,
671
+ /** @type {import('./jsdocUtils.js').ParserMode} */ (mode),
672
+ tagNamePreference,
673
+ context,
674
+ );
675
+ const isObject = ret && typeof ret === 'object';
676
+ if (ret === false || (isObject && !ret.replacement)) {
677
+ return {
678
+ blocked: true,
679
+ tagName,
680
+ };
681
+ }
682
+
683
+ return ret;
684
+ };
685
+
686
+ return utils;
687
+ };
688
+
689
+ /**
690
+ * @callback Report
691
+ * @param {string} message
692
+ * @param {import('@eslint/core').RuleFixer|null} [fix]
693
+ * @param {null|
694
+ * {line?: Integer, column?: Integer}|
695
+ * import('comment-parser').Spec & {line?: Integer}
696
+ * } [jsdocLoc]
697
+ * @param {undefined|{
698
+ * [key: string]: string
699
+ * }} [data]
700
+ * @returns {void}
701
+ */
702
+
703
+ /**
704
+ * @param {Node|null} node
705
+ * @param {JsdocBlockWithInline} jsdoc
706
+ * @param {import('eslint').AST.Token} jsdocNode
707
+ * @param {Settings} settings
708
+ * @param {Report} report
709
+ * @param {import('eslint').Rule.RuleContext} context
710
+ * @param {import('eslint').SourceCode} sc
711
+ * @param {boolean|undefined} iteratingAll
712
+ * @param {RuleConfig} ruleConfig
713
+ * @param {string} indent
714
+ * @returns {Utils}
715
+ */
716
+ const getUtils = (
717
+ node,
718
+ jsdoc,
719
+ jsdocNode,
720
+ settings,
721
+ report,
722
+ context,
723
+ sc,
724
+ iteratingAll,
725
+ ruleConfig,
726
+ indent,
727
+ ) => {
728
+ const ancestors = /** @type {import('eslint').Rule.Node[]} */ (node ?
729
+ (sc.getAncestors ?
730
+ (
731
+ sc.getAncestors(node)
732
+ /* c8 ignore next 5 */
733
+ ) :
734
+ (
735
+ // @ts-expect-error ESLint 8
736
+ context.getAncestors()
737
+ )) :
738
+ []);
739
+
740
+ /* c8 ignore next -- Fallback to deprecated method */
741
+ const {
742
+ // @ts-expect-error ESLint < 10
743
+ sourceCode = context.getSourceCode(),
744
+ } = context;
745
+
746
+ const utils = /** @type {Utils} */ (getBasicUtils(context, settings));
747
+
748
+ const {
749
+ augmentsExtendsReplacesDocs,
750
+ ignoreReplacesDocs,
751
+ implementsReplacesDocs,
752
+ maxLines,
753
+ minLines,
754
+ mode,
755
+ overrideReplacesDocs,
756
+ tagNamePreference,
757
+ } = settings;
758
+
759
+ const functionTypes = [
760
+ 'ArrowFunctionExpression',
761
+ 'FunctionDeclaration',
762
+ 'FunctionExpression',
763
+ 'MethodDefinition',
764
+ ];
765
+
766
+ /** @type {IsIteratingFunction} */
767
+ utils.isIteratingFunction = () => {
768
+ return !iteratingAll || functionTypes.includes(String(node?.type));
769
+ };
770
+
771
+ /** @type {IsIteratingFunction} */
772
+ utils.isIteratingFunctionOrVariable = () => {
773
+ if (utils.isIteratingFunction()) {
774
+ return true;
775
+ }
776
+
777
+ /** @type {import('estree').VariableDeclarator[]} */
778
+ const declarations = node?.type === 'VariableDeclaration' ?
779
+ node.declarations :
780
+ (node?.type === 'ExportNamedDeclaration' && node.declaration?.type === 'VariableDeclaration' ?
781
+ node.declaration.declarations :
782
+ []);
783
+
784
+ return declarations.some(({
785
+ init,
786
+ }) => {
787
+ return functionTypes.includes(String(init?.type));
788
+ });
789
+ };
790
+
791
+ /** @type {IsVirtualFunction} */
792
+ utils.isVirtualFunction = () => {
793
+ return Boolean(iteratingAll) && utils.hasATag([
794
+ 'callback', 'function', 'func', 'method',
795
+ ]);
796
+ };
797
+
798
+ /** @type {Stringify} */
799
+ utils.stringify = (tagBlock, specRewire) => {
800
+ let block;
801
+ if (specRewire) {
802
+ block = rewireSpecs(tagBlock);
803
+ }
804
+
805
+ return commentStringify(/** @type {import('comment-parser').Block} */ (
806
+ specRewire ? block : tagBlock));
807
+ };
808
+
809
+ /** @type {ReportJSDoc} */
810
+ utils.reportJSDoc = (msg, tag, handler, specRewire, data) => {
811
+ report(msg, handler ? /** @type {import('eslint').Rule.ReportFixer} */ (
812
+ fixer,
813
+ ) => {
814
+ const extraFix = handler(fixer);
815
+
816
+ const replacement = utils.stringify(jsdoc, specRewire);
817
+
818
+ if (!replacement) {
819
+ const text = sourceCode.getText();
820
+ const lastLineBreakPos = text.slice(
821
+ 0, jsdocNode.range[0],
822
+ ).search(/\n[ \t]*$/v);
823
+ if (lastLineBreakPos > -1) {
824
+ return [
825
+ fixer.removeRange([
826
+ lastLineBreakPos, jsdocNode.range[1],
827
+ ]),
828
+ /* c8 ignore next 2 -- Guard */
829
+ ...(extraFix ? [
830
+ extraFix,
831
+ ] : []),
832
+ ];
833
+ }
834
+
835
+ return [
836
+ fixer.removeRange(
837
+ (/\s/v).test(text.charAt(jsdocNode.range[1])) ?
838
+ [
839
+ jsdocNode.range[0], jsdocNode.range[1] + 1,
840
+ ] :
841
+ jsdocNode.range,
842
+ ),
843
+ /* c8 ignore next 2 -- Guard */
844
+ ...(extraFix ? [
845
+ extraFix,
846
+ ] : []),
847
+ ];
848
+ }
849
+
850
+ return [
851
+ fixer.replaceText(jsdocNode, replacement),
852
+ ...(extraFix ? [
853
+ extraFix,
854
+ ] : []),
855
+ ];
856
+ } : null, tag, data);
857
+ };
858
+
859
+ /** @type {GetRegexFromString} */
860
+ utils.getRegexFromString = (str, requiredFlags) => {
861
+ return jsdocUtils.getRegexFromString(str, requiredFlags);
862
+ };
863
+
864
+ /** @type {GetTagDescription} */
865
+ utils.getTagDescription = (tg, returnArray) => {
866
+ return jsdocUtils.getTagDescription(tg, returnArray);
867
+ };
868
+
869
+ /** @type {SetTagDescription} */
870
+ utils.setTagDescription = (tg, matcher, setter) => {
871
+ let finalIdx = 0;
872
+ tg.source.some(({
873
+ tokens: {
874
+ description,
875
+ },
876
+ }, idx) => {
877
+ if (description && matcher.test(description)) {
878
+ tg.source[idx].tokens.description = setter(description);
879
+ finalIdx = idx;
880
+ return true;
881
+ }
882
+
883
+ return false;
884
+ });
885
+
886
+ return finalIdx;
887
+ };
888
+
889
+ /** @type {GetDescription} */
890
+ utils.getDescription = () => {
891
+ /** @type {string[]} */
892
+ const descriptions = [];
893
+ let lastDescriptionLine = 0;
894
+ let tagsBegun = false;
895
+ jsdoc.source.some(({
896
+ tokens: {
897
+ description,
898
+ end,
899
+ tag,
900
+ },
901
+ }, idx) => {
902
+ if (tag) {
903
+ tagsBegun = true;
904
+ }
905
+
906
+ if (idx && (tag || end)) {
907
+ lastDescriptionLine = idx - 1;
908
+ if (!tagsBegun && description) {
909
+ descriptions.push(description);
910
+ }
911
+
912
+ return true;
913
+ }
914
+
915
+ if (!tagsBegun && (idx || description)) {
916
+ descriptions.push(description || (descriptions.length ? '' : '\n'));
917
+ }
918
+
919
+ return false;
920
+ });
921
+
922
+ return {
923
+ description: descriptions.join('\n'),
924
+ descriptions,
925
+ lastDescriptionLine,
926
+ };
927
+ };
928
+
929
+ /** @type {SetBlockDescription} */
930
+ utils.setBlockDescription = (setter) => {
931
+ /** @type {string[]} */
932
+ const descLines = [];
933
+ /** @type {string[]} */
934
+ const postDelims = [];
935
+ /**
936
+ * @type {undefined|Integer}
937
+ */
938
+ let startIdx;
939
+ /**
940
+ * @type {undefined|Integer}
941
+ */
942
+ let endIdx;
943
+
944
+ /**
945
+ * @type {undefined|{
946
+ * delimiter: string,
947
+ * postDelimiter: string,
948
+ * start: string
949
+ * }}
950
+ */
951
+ let info;
952
+
953
+ jsdoc.source.some(({
954
+ tokens: {
955
+ delimiter,
956
+ description,
957
+ end,
958
+ postDelimiter,
959
+ start,
960
+ tag,
961
+ },
962
+ }, idx) => {
963
+ if (delimiter === '/**') {
964
+ return false;
965
+ }
966
+
967
+ if (startIdx === undefined) {
968
+ startIdx = idx;
969
+ info = {
970
+ delimiter,
971
+ postDelimiter,
972
+ start,
973
+ };
974
+ }
975
+
976
+ if (tag || end) {
977
+ endIdx = idx;
978
+ return true;
979
+ }
980
+
981
+ postDelims.push(postDelimiter);
982
+ descLines.push(description);
983
+ return false;
984
+ });
985
+
986
+ /* c8 ignore else -- Won't be called if missing */
987
+ if (descLines.length) {
988
+ jsdoc.source.splice(
989
+ /** @type {Integer} */ (startIdx),
990
+ /** @type {Integer} */ (endIdx) - /** @type {Integer} */ (startIdx),
991
+ ...setter(
992
+ /**
993
+ * @type {{
994
+ * delimiter: string,
995
+ * postDelimiter: string,
996
+ * start: string
997
+ * }}
998
+ */
999
+ (info),
1000
+ seedTokens,
1001
+ descLines,
1002
+ postDelims,
1003
+ ),
1004
+ );
1005
+ }
1006
+ };
1007
+
1008
+ /** @type {SetDescriptionLines} */
1009
+ utils.setDescriptionLines = (matcher, setter) => {
1010
+ let finalIdx = 0;
1011
+ jsdoc.source.some(({
1012
+ tokens: {
1013
+ description,
1014
+ end,
1015
+ tag,
1016
+ },
1017
+ }, idx) => {
1018
+ /* c8 ignore next 3 -- Already checked */
1019
+ if (idx && (tag || end)) {
1020
+ return true;
1021
+ }
1022
+
1023
+ if (description && matcher.test(description)) {
1024
+ jsdoc.source[idx].tokens.description = setter(description);
1025
+ finalIdx = idx;
1026
+ return true;
1027
+ }
1028
+
1029
+ return false;
1030
+ });
1031
+
1032
+ return finalIdx;
1033
+ };
1034
+
1035
+ /** @type {ChangeTag} */
1036
+ utils.changeTag = (tag, ...tokens) => {
1037
+ for (const [
1038
+ idx,
1039
+ src,
1040
+ ] of tag.source.entries()) {
1041
+ src.tokens = {
1042
+ ...src.tokens,
1043
+ ...tokens[idx],
1044
+ };
1045
+ }
1046
+ };
1047
+
1048
+ /** @type {SetTag} */
1049
+ utils.setTag = (tag, tokens) => {
1050
+ tag.source = [
1051
+ {
1052
+ number: tag.line,
1053
+ // Or tag.source[0].number?
1054
+ source: '',
1055
+ tokens: seedTokens({
1056
+ delimiter: '*',
1057
+ postDelimiter: ' ',
1058
+ start: indent + ' ',
1059
+ tag: '@' + tag.tag,
1060
+ ...tokens,
1061
+ }),
1062
+ },
1063
+ ];
1064
+ };
1065
+
1066
+ /** @type {RemoveTag} */
1067
+ utils.removeTag = (tagIndex, {
1068
+ removeEmptyBlock = false,
1069
+ tagSourceOffset = 0,
1070
+ } = {}) => {
1071
+ const {
1072
+ source: tagSource,
1073
+ } = jsdoc.tags[tagIndex];
1074
+ /** @type {Integer|undefined} */
1075
+ let lastIndex;
1076
+ const firstNumber = jsdoc.source[0].number;
1077
+ tagSource.some(({
1078
+ number,
1079
+ }, tagIdx) => {
1080
+ const sourceIndex = jsdoc.source.findIndex(({
1081
+ number: srcNumber,
1082
+ }) => {
1083
+ return number === srcNumber;
1084
+ });
1085
+ // c8 ignore else
1086
+ if (sourceIndex > -1) {
1087
+ let spliceCount = 1;
1088
+ tagSource.slice(tagIdx + 1).some(({
1089
+ tokens: {
1090
+ end: ending,
1091
+ tag,
1092
+ },
1093
+ }) => {
1094
+ if (!tag && !ending) {
1095
+ spliceCount++;
1096
+
1097
+ return false;
1098
+ }
1099
+
1100
+ return true;
1101
+ });
1102
+
1103
+ const spliceIdx = sourceIndex + tagSourceOffset;
1104
+
1105
+ const {
1106
+ delimiter,
1107
+ end,
1108
+ } = jsdoc.source[spliceIdx].tokens;
1109
+
1110
+ if (
1111
+ spliceIdx === 0 && jsdoc.tags.length >= 2 ||
1112
+ !removeEmptyBlock && (end || delimiter === '/**')
1113
+ ) {
1114
+ const {
1115
+ tokens,
1116
+ } = jsdoc.source[spliceIdx];
1117
+ for (const item of [
1118
+ 'postDelimiter',
1119
+ 'tag',
1120
+ 'postTag',
1121
+ 'type',
1122
+ 'postType',
1123
+ 'name',
1124
+ 'postName',
1125
+ 'description',
1126
+ ]) {
1127
+ tokens[
1128
+ /**
1129
+ * @type {"postDelimiter"|"tag"|"type"|"postType"|
1130
+ * "postTag"|"name"|"postName"|"description"}
1131
+ */ (
1132
+ item
1133
+ )
1134
+ ] = '';
1135
+ }
1136
+ } else {
1137
+ jsdoc.source.splice(spliceIdx, spliceCount - tagSourceOffset + (spliceIdx ? 0 : jsdoc.source.length));
1138
+ tagSource.splice(tagIdx + tagSourceOffset, spliceCount - tagSourceOffset + (spliceIdx ? 0 : jsdoc.source.length));
1139
+ }
1140
+
1141
+ lastIndex = sourceIndex;
1142
+
1143
+ return true;
1144
+ }
1145
+ /* c8 ignore next 2 */
1146
+ // eslint-disable-next-line @stylistic/padding-line-between-statements -- c8
1147
+ return false;
1148
+ });
1149
+ for (const [
1150
+ idx,
1151
+ src,
1152
+ ] of jsdoc.source.slice(lastIndex).entries()) {
1153
+ src.number = firstNumber + /** @type {Integer} */ (lastIndex) + idx;
1154
+ }
1155
+
1156
+ // Todo: Once rewiring of tags may be fixed in comment-parser to reflect
1157
+ // missing tags, this step should be added here (so that, e.g.,
1158
+ // if accessing `jsdoc.tags`, such as to add a new tag, the
1159
+ // correct information will be available)
1160
+ };
1161
+
1162
+ /** @type {AddTag} */
1163
+ utils.addTag = (
1164
+ targetTagName,
1165
+ number = (jsdoc.tags[jsdoc.tags.length - 1]?.source[0]?.number ?? jsdoc.source.findIndex(({
1166
+ tokens: {
1167
+ tag,
1168
+ },
1169
+ }) => {
1170
+ return tag;
1171
+ }) - 1) + 1,
1172
+ tokens = {},
1173
+ ) => {
1174
+ jsdoc.source.splice(number, 0, {
1175
+ number,
1176
+ source: '',
1177
+ tokens: seedTokens({
1178
+ delimiter: '*',
1179
+ postDelimiter: ' ',
1180
+ start: indent + ' ',
1181
+ tag: `@${targetTagName}`,
1182
+ ...tokens,
1183
+ }),
1184
+ });
1185
+ for (const src of jsdoc.source.slice(number + 1)) {
1186
+ src.number++;
1187
+ }
1188
+ };
1189
+
1190
+ /** @type {GetFirstLine} */
1191
+ utils.getFirstLine = () => {
1192
+ let firstLine;
1193
+ for (const {
1194
+ number,
1195
+ tokens: {
1196
+ tag,
1197
+ },
1198
+ } of jsdoc.source) {
1199
+ if (tag) {
1200
+ firstLine = number;
1201
+ break;
1202
+ }
1203
+ }
1204
+
1205
+ return firstLine;
1206
+ };
1207
+
1208
+ /** @type {SeedTokens} */
1209
+ utils.seedTokens = seedTokens;
1210
+
1211
+ /** @type {EmptyTokens} */
1212
+ utils.emptyTokens = (tokens) => {
1213
+ for (const prop of [
1214
+ 'start',
1215
+ 'postDelimiter',
1216
+ 'tag',
1217
+ 'type',
1218
+ 'postType',
1219
+ 'postTag',
1220
+ 'name',
1221
+ 'postName',
1222
+ 'description',
1223
+ 'end',
1224
+ 'lineEnd',
1225
+ ]) {
1226
+ tokens[
1227
+ /**
1228
+ * @type {"start"|"postDelimiter"|"tag"|"type"|"postType"|
1229
+ * "postTag"|"name"|"postName"|"description"|"end"|"lineEnd"}
1230
+ */ (
1231
+ prop
1232
+ )
1233
+ ] = '';
1234
+ }
1235
+ };
1236
+
1237
+ /** @type {AddLine} */
1238
+ utils.addLine = (sourceIndex, tokens) => {
1239
+ const number = (jsdoc.source[sourceIndex - 1]?.number || 0) + 1;
1240
+ jsdoc.source.splice(sourceIndex, 0, {
1241
+ number,
1242
+ source: '',
1243
+ tokens: seedTokens(tokens),
1244
+ });
1245
+
1246
+ for (const src of jsdoc.source.slice(number + 1)) {
1247
+ src.number++;
1248
+ }
1249
+ // If necessary, we can rewire the tags (misnamed method)
1250
+ // rewireSource(jsdoc);
1251
+ };
1252
+
1253
+ /** @type {AddLines} */
1254
+ utils.addLines = (tagIndex, tagSourceOffset, numLines) => {
1255
+ const {
1256
+ source: tagSource,
1257
+ } = jsdoc.tags[tagIndex];
1258
+ /** @type {Integer|undefined} */
1259
+ let lastIndex;
1260
+ const firstNumber = jsdoc.source[0].number;
1261
+ tagSource.some(({
1262
+ number,
1263
+ }) => {
1264
+ const makeLine = () => {
1265
+ return {
1266
+ number,
1267
+ source: '',
1268
+ tokens: seedTokens({
1269
+ delimiter: '*',
1270
+ start: indent + ' ',
1271
+ }),
1272
+ };
1273
+ };
1274
+
1275
+ const makeLines = () => {
1276
+ return Array.from({
1277
+ length: numLines,
1278
+ }, makeLine);
1279
+ };
1280
+
1281
+ const sourceIndex = jsdoc.source.findIndex(({
1282
+ number: srcNumber,
1283
+ tokens: {
1284
+ end,
1285
+ },
1286
+ }) => {
1287
+ return number === srcNumber && !end;
1288
+ });
1289
+ // c8 ignore else
1290
+ if (sourceIndex > -1) {
1291
+ const lines = makeLines();
1292
+ jsdoc.source.splice(sourceIndex + tagSourceOffset, 0, ...lines);
1293
+
1294
+ // tagSource.splice(tagIdx + 1, 0, ...makeLines());
1295
+ lastIndex = sourceIndex;
1296
+
1297
+ return true;
1298
+ }
1299
+ /* c8 ignore next 2 */
1300
+ // eslint-disable-next-line @stylistic/padding-line-between-statements -- c8
1301
+ return false;
1302
+ });
1303
+
1304
+ for (const [
1305
+ idx,
1306
+ src,
1307
+ ] of jsdoc.source.slice(lastIndex).entries()) {
1308
+ src.number = firstNumber + /** @type {Integer} */ (lastIndex) + idx;
1309
+ }
1310
+ };
1311
+
1312
+ /** @type {MakeMultiline} */
1313
+ utils.makeMultiline = () => {
1314
+ const {
1315
+ source: [
1316
+ {
1317
+ tokens,
1318
+ },
1319
+ ],
1320
+ } = jsdoc;
1321
+ const {
1322
+ description,
1323
+ lineEnd,
1324
+ name,
1325
+ postDelimiter,
1326
+ tag,
1327
+ type,
1328
+ } = tokens;
1329
+
1330
+ let {
1331
+ tokens: {
1332
+ postName,
1333
+ postTag,
1334
+ postType,
1335
+ },
1336
+ } = jsdoc.source[0];
1337
+
1338
+ // Strip trailing leftovers from single line ending
1339
+ if (!description) {
1340
+ if (postName) {
1341
+ postName = '';
1342
+ } else if (postType) {
1343
+ postType = '';
1344
+ } else /* c8 ignore else -- `comment-parser` prevents empty blocks currently per https://github.com/syavorsky/comment-parser/issues/128 */ if (postTag) {
1345
+ postTag = '';
1346
+ }
1347
+ }
1348
+
1349
+ utils.emptyTokens(tokens);
1350
+
1351
+ utils.addLine(1, {
1352
+ delimiter: '*',
1353
+
1354
+ // If a description were present, it may have whitespace attached
1355
+ // due to being at the end of the single line
1356
+ description: description.trimEnd(),
1357
+ name,
1358
+ postDelimiter,
1359
+ postName,
1360
+ postTag,
1361
+ postType,
1362
+ start: indent + ' ',
1363
+ tag,
1364
+ type,
1365
+ });
1366
+ utils.addLine(2, {
1367
+ end: '*/',
1368
+ lineEnd,
1369
+ start: indent + ' ',
1370
+ });
1371
+ };
1372
+
1373
+ /**
1374
+ * @type {import('./jsdocUtils.js').FlattenRoots}
1375
+ */
1376
+ utils.flattenRoots = jsdocUtils.flattenRoots;
1377
+
1378
+ /** @type {GetFunctionParameterNames} */
1379
+ utils.getFunctionParameterNames = (useDefaultObjectProperties, ignoreInterfacedParameters) => {
1380
+ return jsdocUtils.getFunctionParameterNames(node, useDefaultObjectProperties, ignoreInterfacedParameters);
1381
+ };
1382
+
1383
+ /** @type {HasParams} */
1384
+ utils.hasParams = () => {
1385
+ return jsdocUtils.hasParams(/** @type {Node} */ (node));
1386
+ };
1387
+
1388
+ /** @type {IsGenerator} */
1389
+ utils.isGenerator = () => {
1390
+ return node !== null && Boolean(
1391
+ /**
1392
+ * @type {import('estree').FunctionDeclaration|
1393
+ * import('estree').FunctionExpression}
1394
+ */ (node).generator ||
1395
+ node.type === 'MethodDefinition' && node.value.generator ||
1396
+ [
1397
+ 'ExportDefaultDeclaration', 'ExportNamedDeclaration',
1398
+ ].includes(node.type) &&
1399
+ /** @type {import('estree').FunctionDeclaration} */
1400
+ (
1401
+ /**
1402
+ * @type {import('estree').ExportNamedDeclaration|
1403
+ * import('estree').ExportDefaultDeclaration}
1404
+ */ (node).declaration
1405
+ )?.generator,
1406
+ );
1407
+ };
1408
+
1409
+ /** @type {IsConstructor} */
1410
+ utils.isConstructor = () => {
1411
+ return jsdocUtils.isConstructor(/** @type {Node} */ (node));
1412
+ };
1413
+
1414
+ /** @type {GetJsdocTagsDeep} */
1415
+ utils.getJsdocTagsDeep = (tagName) => {
1416
+ const name = /** @type {string|false} */ (utils.getPreferredTagName({
1417
+ tagName,
1418
+ }));
1419
+ if (!name) {
1420
+ return false;
1421
+ }
1422
+
1423
+ return jsdocUtils.getJsdocTagsDeep(jsdoc, name);
1424
+ };
1425
+
1426
+ /** @type {GetPreferredTagName} */
1427
+ utils.getPreferredTagName = (args) => {
1428
+ return jsdocUtils.getPreferredTagName(
1429
+ jsdoc, {
1430
+ ...args,
1431
+ context,
1432
+ mode,
1433
+ report,
1434
+ tagNamePreference,
1435
+ },
1436
+ );
1437
+ };
1438
+
1439
+ /** @type {IsValidTag} */
1440
+ utils.isValidTag = (name, definedTags) => {
1441
+ return jsdocUtils.isValidTag(context, mode, name, definedTags);
1442
+ };
1443
+
1444
+ /** @type {HasATag} */
1445
+ utils.hasATag = (names) => {
1446
+ return jsdocUtils.hasATag(jsdoc, names);
1447
+ };
1448
+
1449
+ /** @type {HasTag} */
1450
+ utils.hasTag = (name) => {
1451
+ return jsdocUtils.hasTag(jsdoc, name);
1452
+ };
1453
+
1454
+ /** @type {ComparePaths} */
1455
+ utils.comparePaths = (name) => {
1456
+ return jsdocUtils.comparePaths(name);
1457
+ };
1458
+
1459
+ /** @type {DropPathSegmentQuotes} */
1460
+ utils.dropPathSegmentQuotes = (name) => {
1461
+ return jsdocUtils.dropPathSegmentQuotes(name);
1462
+ };
1463
+
1464
+ /** @type {AvoidDocs} */
1465
+ utils.avoidDocs = () => {
1466
+ if (
1467
+ ignoreReplacesDocs !== false &&
1468
+ (utils.hasTag('ignore') || utils.classHasTag('ignore')) ||
1469
+ overrideReplacesDocs !== false &&
1470
+ (utils.hasTag('override') || utils.classHasTag('override')) ||
1471
+ implementsReplacesDocs !== false &&
1472
+ (utils.hasTag('implements') || utils.classHasTag('implements')) ||
1473
+
1474
+ augmentsExtendsReplacesDocs &&
1475
+ (utils.hasATag([
1476
+ 'augments', 'extends',
1477
+ ]) ||
1478
+ utils.classHasTag('augments') ||
1479
+ utils.classHasTag('extends'))) {
1480
+ return true;
1481
+ }
1482
+
1483
+ if (jsdocUtils.exemptSpeciaMethods(
1484
+ jsdoc,
1485
+ node,
1486
+ context,
1487
+ /** @type {import('json-schema').JSONSchema4|import('json-schema').JSONSchema4[]} */ (
1488
+ ruleConfig.meta.schema
1489
+ ),
1490
+ )) {
1491
+ return true;
1492
+ }
1493
+
1494
+ const exemptedBy = context.options[0]?.exemptedBy ?? [
1495
+ 'inheritDoc',
1496
+ ...mode === 'closure' ? [] : [
1497
+ 'inheritdoc',
1498
+ ],
1499
+ ];
1500
+ if (exemptedBy.length && utils.getPresentTags(exemptedBy).length) {
1501
+ return true;
1502
+ }
1503
+
1504
+ return false;
1505
+ };
1506
+
1507
+ for (const method of [
1508
+ 'tagMightHaveNamePosition',
1509
+ 'tagMightHaveTypePosition',
1510
+ ]) {
1511
+ /** @type {TagMightHaveNamePositionTypePosition} */
1512
+ utils[
1513
+ /** @type {"tagMightHaveNamePosition"|"tagMightHaveTypePosition"} */ (
1514
+ method
1515
+ )
1516
+ ] = (tagName, otherModeMaps) => {
1517
+ const result = jsdocUtils[
1518
+ /** @type {"tagMightHaveNamePosition"|"tagMightHaveTypePosition"} */
1519
+ (method)
1520
+ ](tagName);
1521
+ if (result) {
1522
+ return true;
1523
+ }
1524
+
1525
+ if (!otherModeMaps) {
1526
+ return false;
1527
+ }
1528
+
1529
+ const otherResult = otherModeMaps.some((otherModeMap) => {
1530
+ return jsdocUtils[
1531
+ /** @type {"tagMightHaveNamePosition"|"tagMightHaveTypePosition"} */
1532
+ (method)
1533
+ ](tagName, otherModeMap);
1534
+ });
1535
+
1536
+ return otherResult ? {
1537
+ otherMode: true,
1538
+ } : false;
1539
+ };
1540
+ }
1541
+
1542
+ /** @type {TagMissingRequiredTypeOrNamepath} */
1543
+ utils.tagMissingRequiredTypeOrNamepath = (tagName, otherModeMaps) => {
1544
+ const result = jsdocUtils.tagMissingRequiredTypeOrNamepath(tagName);
1545
+ if (!result) {
1546
+ return false;
1547
+ }
1548
+
1549
+ const otherResult = otherModeMaps.every((otherModeMap) => {
1550
+ return jsdocUtils.tagMissingRequiredTypeOrNamepath(tagName, otherModeMap);
1551
+ });
1552
+
1553
+ return otherResult ? true : {
1554
+ otherMode: false,
1555
+ };
1556
+ };
1557
+
1558
+ for (const method of [
1559
+ 'tagMustHaveNamePosition',
1560
+ 'tagMustHaveTypePosition',
1561
+ ]) {
1562
+ /** @type {TagMustHave} */
1563
+ utils[
1564
+ /** @type {"tagMustHaveNamePosition"|"tagMustHaveTypePosition"} */
1565
+ (method)
1566
+ ] = (tagName, otherModeMaps) => {
1567
+ const result = jsdocUtils[
1568
+ /** @type {"tagMustHaveNamePosition"|"tagMustHaveTypePosition"} */
1569
+ (method)
1570
+ ](tagName);
1571
+ if (!result) {
1572
+ return false;
1573
+ }
1574
+
1575
+ // if (!otherModeMaps) { return true; }
1576
+
1577
+ const otherResult = otherModeMaps.every((otherModeMap) => {
1578
+ return jsdocUtils[
1579
+ /** @type {"tagMustHaveNamePosition"|"tagMustHaveTypePosition"} */
1580
+ (method)
1581
+ ](tagName, otherModeMap);
1582
+ });
1583
+
1584
+ return otherResult ? true : {
1585
+ otherMode: false,
1586
+ };
1587
+ };
1588
+ }
1589
+
1590
+ /** @type {GetTagStructureForMode} */
1591
+ utils.getTagStructureForMode = (mde) => {
1592
+ return jsdocUtils.getTagStructureForMode(mde, settings.structuredTags);
1593
+ };
1594
+
1595
+ /** @type {MayBeUndefinedTypeTag} */
1596
+ utils.mayBeUndefinedTypeTag = (tag) => {
1597
+ return jsdocUtils.mayBeUndefinedTypeTag(tag, settings.mode);
1598
+ };
1599
+
1600
+ /** @type {HasValueOrExecutorHasNonEmptyResolveValue} */
1601
+ utils.hasValueOrExecutorHasNonEmptyResolveValue = (anyPromiseAsReturn, allBranches) => {
1602
+ return jsdocUtils.hasValueOrExecutorHasNonEmptyResolveValue(
1603
+ /** @type {Node} */ (node), anyPromiseAsReturn, allBranches,
1604
+ );
1605
+ };
1606
+
1607
+ /** @type {HasYieldValue} */
1608
+ utils.hasYieldValue = () => {
1609
+ if ([
1610
+ 'ExportDefaultDeclaration', 'ExportNamedDeclaration',
1611
+ ].includes(/** @type {Node} */ (node).type)) {
1612
+ return jsdocUtils.hasYieldValue(
1613
+ /** @type {import('estree').Declaration|import('estree').Expression} */ (
1614
+ /** @type {import('estree').ExportNamedDeclaration|import('estree').ExportDefaultDeclaration} */
1615
+ (node).declaration
1616
+ ),
1617
+ );
1618
+ }
1619
+
1620
+ return jsdocUtils.hasYieldValue(/** @type {Node} */ (node));
1621
+ };
1622
+
1623
+ /** @type {HasYieldReturnValue} */
1624
+ utils.hasYieldReturnValue = () => {
1625
+ return jsdocUtils.hasYieldValue(/** @type {Node} */ (node), true);
1626
+ };
1627
+
1628
+ /** @type {HasThrowValue} */
1629
+ utils.hasThrowValue = () => {
1630
+ return jsdocUtils.hasThrowValue(node);
1631
+ };
1632
+
1633
+ /** @type {IsAsync} */
1634
+ utils.isAsync = () => {
1635
+ return Boolean(node && 'async' in node && node.async);
1636
+ };
1637
+
1638
+ /** @type {GetTags} */
1639
+ utils.getTags = (tagName) => {
1640
+ return jsdocUtils.getTags(jsdoc, tagName);
1641
+ };
1642
+
1643
+ /** @type {GetPresentTags} */
1644
+ utils.getPresentTags = (tagList) => {
1645
+ return jsdocUtils.filterTags(jsdoc, (tag) => {
1646
+ return tagList.includes(tag.tag);
1647
+ });
1648
+ };
1649
+
1650
+ /** @type {FilterTags} */
1651
+ utils.filterTags = (filter) => {
1652
+ return jsdocUtils.filterTags(jsdoc, (tag) => {
1653
+ return filter(tag);
1654
+ });
1655
+ };
1656
+
1657
+ /** @type {FilterAllTags} */
1658
+ utils.filterAllTags = (filter) => {
1659
+ const tags = jsdocUtils.getAllTags(jsdoc);
1660
+ return tags.filter((tag) => {
1661
+ return filter(tag);
1662
+ });
1663
+ };
1664
+
1665
+ utils.getInlineTags = () => {
1666
+ return jsdocUtils.getInlineTags(jsdoc);
1667
+ };
1668
+
1669
+ /** @type {GetTagsByType} */
1670
+ utils.getTagsByType = (tags) => {
1671
+ return jsdocUtils.getTagsByType(context, mode, tags);
1672
+ };
1673
+
1674
+ /** @type {HasOptionTag} */
1675
+ utils.hasOptionTag = (tagName) => {
1676
+ const {
1677
+ tags,
1678
+ } = context.options[0] ?? {};
1679
+
1680
+ return Boolean(tags && tags.includes(tagName));
1681
+ };
1682
+
1683
+ /** @type {GetClassNode} */
1684
+ utils.getClassNode = () => {
1685
+ return [
1686
+ ...ancestors, node,
1687
+ ].toReversed().find((parent) => {
1688
+ return parent && [
1689
+ 'ClassDeclaration', 'ClassExpression',
1690
+ ].includes(parent.type);
1691
+ }) ?? null;
1692
+ };
1693
+
1694
+ /** @type {GetClassJsdoc} */
1695
+ utils.getClassJsdoc = () => {
1696
+ const classNode = utils.getClassNode();
1697
+
1698
+ if (!classNode) {
1699
+ return null;
1700
+ }
1701
+
1702
+ const classJsdocNode = getJSDocComment(sourceCode, classNode, {
1703
+ maxLines,
1704
+ minLines,
1705
+ });
1706
+
1707
+ if (classJsdocNode) {
1708
+ return parseComment(classJsdocNode, '');
1709
+ }
1710
+
1711
+ return null;
1712
+ };
1713
+
1714
+ /** @type {ClassHasTag} */
1715
+ utils.classHasTag = (tagName) => {
1716
+ const classJsdoc = utils.getClassJsdoc();
1717
+
1718
+ return classJsdoc !== null && jsdocUtils.hasTag(classJsdoc, tagName);
1719
+ };
1720
+
1721
+ /** @type {ForEachPreferredTag} */
1722
+ utils.forEachPreferredTag = (tagName, arrayHandler, skipReportingBlockedTag) => {
1723
+ return jsdocUtils.forEachPreferredTag(
1724
+ jsdoc, tagName, arrayHandler, {
1725
+ context,
1726
+ mode,
1727
+ report,
1728
+ skipReportingBlockedTag,
1729
+ tagNamePreference,
1730
+ },
1731
+ );
1732
+ };
1733
+
1734
+ /** @type {FindContext} */
1735
+ utils.findContext = (contexts, comment) => {
1736
+ const foundContext = contexts.find((cntxt) => {
1737
+ return typeof cntxt === 'string' ?
1738
+ esquery.matches(
1739
+ /** @type {Node} */ (node),
1740
+ esquery.parse(cntxt),
1741
+ undefined,
1742
+ {
1743
+ visitorKeys: sourceCode.visitorKeys,
1744
+ },
1745
+ ) :
1746
+ (!cntxt.context || cntxt.context === 'any' ||
1747
+ esquery.matches(
1748
+ /** @type {Node} */ (node),
1749
+ esquery.parse(cntxt.context),
1750
+ undefined,
1751
+ {
1752
+ visitorKeys: sourceCode.visitorKeys,
1753
+ },
1754
+ )) && comment === cntxt.comment;
1755
+ });
1756
+
1757
+ const contextStr = typeof foundContext === 'object' ?
1758
+ foundContext.context ?? 'any' :
1759
+ String(foundContext);
1760
+
1761
+ return {
1762
+ contextStr,
1763
+ foundContext,
1764
+ };
1765
+ };
1766
+
1767
+ return utils;
1768
+ };
1769
+
1770
+ /**
1771
+ * @typedef {{
1772
+ * [key: string]: false|string|{
1773
+ * message: string,
1774
+ * replacement?: false|string
1775
+ * skipRootChecking?: boolean
1776
+ * unifyParentAndChildTypeChecks?: boolean
1777
+ * }
1778
+ * }} PreferredTypes
1779
+ */
1780
+ /**
1781
+ * @typedef {{
1782
+ * [key: string]: {
1783
+ * name?: "text"|"name-defining"|"namepath-defining"|"namepath-referencing"|false,
1784
+ * type?: boolean|string[],
1785
+ * required?: ("name"|"type"|"typeOrNameRequired")[]
1786
+ * }
1787
+ * }} StructuredTags
1788
+ */
1789
+ /**
1790
+ * Settings from ESLint types.
1791
+ * @typedef {{
1792
+ * maxLines: Integer,
1793
+ * minLines: Integer,
1794
+ * tagNamePreference: import('./jsdocUtils.js').TagNamePreference,
1795
+ * mode: import('./jsdocUtils.js').ParserMode,
1796
+ * preferredTypes: PreferredTypes,
1797
+ * structuredTags: StructuredTags,
1798
+ * contexts?: Context[],
1799
+ * augmentsExtendsReplacesDocs?: boolean,
1800
+ * ignoreReplacesDocs?: boolean,
1801
+ * implementsReplacesDocs?: boolean,
1802
+ * overrideReplacesDocs?: boolean,
1803
+ * ignoreInternal?: boolean,
1804
+ * ignorePrivate?: boolean,
1805
+ * exemptDestructuredRootsFromChecks?: boolean,
1806
+ * skipInvokedExpressionsForCommentFinding?: boolean
1807
+ * }} Settings
1808
+ */
1809
+
1810
+ /**
1811
+ * @typedef {{
1812
+ * settings?: {
1813
+ * jsdoc?: {
1814
+ * ignorePrivate: boolean,
1815
+ * ignoreInternal: boolean,
1816
+ * maxLines: Integer,
1817
+ * minLines: Integer,
1818
+ * tagNamePreference: import('./jsdocUtils.js').TagNamePreference,
1819
+ * preferredTypes: PreferredTypes,
1820
+ * structuredTags: StructuredTags,
1821
+ * overrideReplacesDocs: boolean,
1822
+ * ignoreReplacesDocs: boolean,
1823
+ * implementsReplacesDocs: boolean,
1824
+ * augmentsExtendsReplacesDocs: boolean,
1825
+ * exemptDestructuredRootsFromChecks: boolean,
1826
+ * skipInvokedExpressionsForCommentFinding: boolean,
1827
+ * mode: import('./jsdocUtils.js').ParserMode,
1828
+ * contexts: Context[],
1829
+ * }
1830
+ * }
1831
+ * }} JSDocSettings
1832
+ */
1833
+
1834
+ /**
1835
+ * @param {import('eslint').Rule.RuleContext & JSDocSettings} context
1836
+ * @returns {Settings|false}
1837
+ */
1838
+ const getSettings = (context) => {
1839
+ /* eslint-disable perfectionist/sort-objects */
1840
+ const settings = {
1841
+ // All rules
1842
+ ignorePrivate: Boolean(context.settings.jsdoc?.ignorePrivate),
1843
+ ignoreInternal: Boolean(context.settings.jsdoc?.ignoreInternal),
1844
+ maxLines: Number(context.settings.jsdoc?.maxLines ?? 1),
1845
+ minLines: Number(context.settings.jsdoc?.minLines ?? 0),
1846
+ skipInvokedExpressionsForCommentFinding:
1847
+ Boolean(context.settings.jsdoc?.skipInvokedExpressionsForCommentFinding),
1848
+
1849
+ // `check-tag-names` and many returns/param rules
1850
+ tagNamePreference: context.settings.jsdoc?.tagNamePreference ?? {},
1851
+
1852
+ // `check-types` and `no-undefined-types`
1853
+ preferredTypes: context.settings.jsdoc?.preferredTypes ?? {},
1854
+
1855
+ // `check-types`, `no-undefined-types`, `valid-types`
1856
+ structuredTags: context.settings.jsdoc?.structuredTags ?? {},
1857
+
1858
+ // `require-param`, `require-description`, `require-example`,
1859
+ // `require-returns`, `require-throw`, `require-yields`
1860
+ overrideReplacesDocs: context.settings.jsdoc?.overrideReplacesDocs,
1861
+ ignoreReplacesDocs: context.settings.jsdoc?.ignoreReplacesDocs,
1862
+ implementsReplacesDocs: context.settings.jsdoc?.implementsReplacesDocs,
1863
+ augmentsExtendsReplacesDocs: context.settings.jsdoc?.augmentsExtendsReplacesDocs,
1864
+
1865
+ // `require-param-type`, `require-param-description`
1866
+ exemptDestructuredRootsFromChecks: context.settings.jsdoc?.exemptDestructuredRootsFromChecks,
1867
+
1868
+ // Many rules, e.g., `check-tag-names`
1869
+ mode: context.settings.jsdoc?.mode ?? 'typescript',
1870
+
1871
+ // Many rules
1872
+ contexts: context.settings.jsdoc?.contexts,
1873
+ };
1874
+ /* eslint-enable perfectionist/sort-objects */
1875
+
1876
+ jsdocUtils.setTagStructure(settings.mode);
1877
+ try {
1878
+ jsdocUtils.overrideTagStructure(settings.structuredTags);
1879
+ } catch (error) {
1880
+ context.report({
1881
+ loc: {
1882
+ end: {
1883
+ column: 1,
1884
+ line: 1,
1885
+ },
1886
+ start: {
1887
+ column: 1,
1888
+ line: 1,
1889
+ },
1890
+ },
1891
+ message: /** @type {Error} */ (error).message,
1892
+ });
1893
+
1894
+ return false;
1895
+ }
1896
+
1897
+ return settings;
1898
+ };
1899
+
1900
+ /**
1901
+ * Create the report function
1902
+ * @callback MakeReport
1903
+ * @param {import('eslint').Rule.RuleContext} context
1904
+ * @param {import('estree').Node} commentNode
1905
+ * @returns {Report}
1906
+ */
1907
+
1908
+ /** @type {MakeReport} */
1909
+ const makeReport = (context, commentNode) => {
1910
+ /** @type {Report} */
1911
+ const report = (message, fix = null, jsdocLoc = null, data = undefined) => {
1912
+ let loc;
1913
+
1914
+ if (jsdocLoc) {
1915
+ if (!('line' in jsdocLoc)) {
1916
+ jsdocLoc.line = /** @type {import('comment-parser').Spec & {line?: Integer}} */ (
1917
+ jsdocLoc
1918
+ ).source[0].number;
1919
+ }
1920
+
1921
+ const lineNumber = /** @type {import('eslint').AST.SourceLocation} */ (
1922
+ commentNode.loc
1923
+ ).start.line +
1924
+ /** @type {Integer} */ (jsdocLoc.line);
1925
+
1926
+ loc = {
1927
+ end: {
1928
+ column: 0,
1929
+ line: lineNumber,
1930
+ },
1931
+ start: {
1932
+ column: 0,
1933
+ line: lineNumber,
1934
+ },
1935
+ };
1936
+
1937
+ if ('column' in jsdocLoc && typeof jsdocLoc.column === 'number') {
1938
+ const colNumber = /** @type {import('eslint').AST.SourceLocation} */ (
1939
+ commentNode.loc
1940
+ ).start.column + jsdocLoc.column;
1941
+
1942
+ loc.end.column = colNumber;
1943
+ loc.start.column = colNumber;
1944
+ }
1945
+ }
1946
+
1947
+ context.report({
1948
+ data,
1949
+ fix,
1950
+ loc,
1951
+ message,
1952
+ node: commentNode,
1953
+ });
1954
+ };
1955
+
1956
+ return report;
1957
+ };
1958
+
1959
+ /**
1960
+ * @typedef {(
1961
+ * arg: {
1962
+ * context: import('eslint').Rule.RuleContext,
1963
+ * sourceCode: import('eslint').SourceCode,
1964
+ * indent?: string,
1965
+ * info?: {
1966
+ * comment?: string|undefined,
1967
+ * lastIndex?: Integer|undefined
1968
+ * },
1969
+ * state?: StateObject,
1970
+ * globalState?: Map<string, Map<string, string>>,
1971
+ * jsdoc?: JsdocBlockWithInline,
1972
+ * jsdocNode?: import('eslint').Rule.Node & {
1973
+ * range: [number, number]
1974
+ * },
1975
+ * node?: Node,
1976
+ * allComments?: import('estree').Node[]
1977
+ * report?: Report,
1978
+ * makeReport?: MakeReport,
1979
+ * settings: Settings,
1980
+ * utils: BasicUtils,
1981
+ * }
1982
+ * ) => void } JsdocVisitorBasic
1983
+ */
1984
+ /**
1985
+ * @typedef {(
1986
+ * arg: {
1987
+ * context: import('eslint').Rule.RuleContext,
1988
+ * sourceCode: import('eslint').SourceCode,
1989
+ * indent: string,
1990
+ * info: {
1991
+ * comment?: string|undefined,
1992
+ * lastIndex?: Integer|undefined
1993
+ * },
1994
+ * state: StateObject,
1995
+ * globalState: Map<string, Map<string, string>>,
1996
+ * jsdoc: JsdocBlockWithInline,
1997
+ * jsdocNode: import('eslint').Rule.Node & {
1998
+ * range: [number, number]
1999
+ * },
2000
+ * node: Node|null,
2001
+ * allComments?: import('estree').Node[]
2002
+ * report: Report,
2003
+ * makeReport?: MakeReport,
2004
+ * settings: Settings,
2005
+ * utils: Utils,
2006
+ * }
2007
+ * ) => void } JsdocVisitor
2008
+ */
2009
+
2010
+ /**
2011
+ * @param {{
2012
+ * comment?: string,
2013
+ * lastIndex?: Integer,
2014
+ * selector?: string,
2015
+ * isFunctionContext?: boolean,
2016
+ * }} info
2017
+ * @param {string} indent
2018
+ * @param {JsdocBlockWithInline} jsdoc
2019
+ * @param {RuleConfig} ruleConfig
2020
+ * @param {import('eslint').Rule.RuleContext} context
2021
+ * @param {import('@es-joy/jsdoccomment').Token} jsdocNode
2022
+ * @param {Node|null} node
2023
+ * @param {Settings} settings
2024
+ * @param {import('eslint').SourceCode} sourceCode
2025
+ * @param {JsdocVisitor} iterator
2026
+ * @param {StateObject} state
2027
+ * @param {boolean} [iteratingAll]
2028
+ * @returns {void}
2029
+ */
2030
+ const iterate = (
2031
+ info,
2032
+ indent, jsdoc,
2033
+ ruleConfig, context, jsdocNode, node, settings,
2034
+ sourceCode, iterator, state, iteratingAll,
2035
+ ) => {
2036
+ const jsdocNde = /** @type {unknown} */ (jsdocNode);
2037
+ const report = makeReport(
2038
+ context,
2039
+ /** @type {import('estree').Node} */
2040
+ (jsdocNde),
2041
+ );
2042
+
2043
+ const utils = getUtils(
2044
+ node,
2045
+ jsdoc,
2046
+ /** @type {import('eslint').AST.Token} */
2047
+ (jsdocNode),
2048
+ settings,
2049
+ report,
2050
+ context,
2051
+ sourceCode,
2052
+ iteratingAll,
2053
+ ruleConfig,
2054
+ indent,
2055
+ );
2056
+
2057
+ if (
2058
+ !ruleConfig.checkInternal && settings.ignoreInternal &&
2059
+ utils.hasTag('internal')
2060
+ ) {
2061
+ return;
2062
+ }
2063
+
2064
+ if (
2065
+ !ruleConfig.checkPrivate && settings.ignorePrivate &&
2066
+ (
2067
+ utils.hasTag('private') ||
2068
+ jsdocUtils
2069
+ .filterTags(jsdoc, ({
2070
+ tag,
2071
+ }) => {
2072
+ return tag === 'access';
2073
+ })
2074
+ .some(({
2075
+ description,
2076
+ }) => {
2077
+ return description === 'private';
2078
+ })
2079
+ )
2080
+ ) {
2081
+ return;
2082
+ }
2083
+
2084
+ iterator({
2085
+ context,
2086
+ globalState,
2087
+ indent,
2088
+ info,
2089
+ jsdoc,
2090
+ jsdocNode: /**
2091
+ * @type {import('eslint').Rule.Node & {
2092
+ * range: [number, number];}}
2093
+ */ (jsdocNde),
2094
+ node,
2095
+ report,
2096
+ settings,
2097
+ sourceCode,
2098
+ state,
2099
+ utils,
2100
+ });
2101
+ };
2102
+
2103
+ /**
2104
+ * @param {string[]} lines
2105
+ * @param {import('estree').Comment} jsdocNode
2106
+ * @returns {[indent: string, jsdoc: JsdocBlockWithInline]}
2107
+ */
2108
+ const getIndentAndJSDoc = function (lines, jsdocNode) {
2109
+ const sourceLine = lines[
2110
+ /** @type {import('estree').SourceLocation} */
2111
+ (jsdocNode.loc).start.line - 1
2112
+ ];
2113
+
2114
+ let indentChar = sourceLine.charAt(0);
2115
+ if (indentChar !== ' ' && indentChar !== '\t') {
2116
+ indentChar = ' ';
2117
+ }
2118
+
2119
+ const indnt = indentChar.repeat(
2120
+ /** @type {import('estree').SourceLocation} */
2121
+ (jsdocNode.loc).start.column,
2122
+ );
2123
+
2124
+ const jsdc = parseComment(jsdocNode, '');
2125
+
2126
+ return [
2127
+ indnt, jsdc,
2128
+ ];
2129
+ };
2130
+
2131
+ /**
2132
+ *
2133
+ * @typedef {{node: Node, state: StateObject}} NonCommentArgs
2134
+ */
2135
+
2136
+ /**
2137
+ * @typedef {object} RuleConfig
2138
+ * @property {EslintRuleMeta} meta ESLint rule meta
2139
+ * @property {import('./jsdocUtils.js').DefaultContexts} [contextDefaults] Any default contexts
2140
+ * @property {true} [contextSelected] Whether to force a `contexts` check
2141
+ * @property {(context: import('eslint').Rule.RuleContext) => import('eslint').Rule.RuleContext} [modifyContext] Modify the rule's context object
2142
+ * @property {true} [iterateAllJsdocs] Whether to iterate all JSDoc blocks by default
2143
+ * regardless of context
2144
+ * @property {true} [checkPrivate] Whether to check `@private` blocks (normally exempted)
2145
+ * @property {true} [checkInternal] Whether to check `@internal` blocks (normally exempted)
2146
+ * @property {true} [checkFile] Whether to iterates over all JSDoc blocks regardless of attachment
2147
+ * @property {true} [nonGlobalSettings] Whether to avoid relying on settings for global contexts
2148
+ * @property {true} [noTracking] Whether to disable the tracking of visited comment nodes (as
2149
+ * non-tracked may conduct further actions)
2150
+ * @property {true} [matchContext] Whether the rule expects contexts to be based on a match option
2151
+ * @property {(args: {
2152
+ * context: import('eslint').Rule.RuleContext,
2153
+ * state: StateObject,
2154
+ * settings: Settings,
2155
+ * utils: BasicUtils
2156
+ * }) => void} [exit] Handler to be executed upon exiting iteration of program AST
2157
+ * @property {(nca: NonCommentArgs) => void} [nonComment] Handler to be executed if rule wishes
2158
+ * to be supplied nodes without comments
2159
+ */
2160
+
2161
+ /**
2162
+ * Create an eslint rule that iterates over all JSDocs, regardless of whether
2163
+ * they are attached to a function-like node.
2164
+ * @param {JsdocVisitor} iterator
2165
+ * @param {RuleConfig} ruleConfig The rule's configuration
2166
+ * @param {ContextObject[]|null} [contexts] The `contexts` containing relevant `comment` info.
2167
+ * @param {boolean} [additiveCommentContexts] If true, will have a separate
2168
+ * iteration for each matching comment context. Otherwise, will iterate
2169
+ * once if there is a single matching comment context.
2170
+ * @returns {import('eslint').Rule.RuleModule}
2171
+ */
2172
+ const iterateAllJsdocs = (iterator, ruleConfig, contexts, additiveCommentContexts) => {
2173
+ const trackedJsdocs = new Set();
2174
+
2175
+ /** @type {import('@es-joy/jsdoccomment').CommentHandler} */
2176
+ let handler;
2177
+
2178
+ /** @type {Settings|false} */
2179
+ let settings;
2180
+
2181
+ /**
2182
+ * @param {import('eslint').Rule.RuleContext} context
2183
+ * @param {Node|null} node
2184
+ * @param {import('estree').Comment[]} jsdocNodes
2185
+ * @param {StateObject} state
2186
+ * @param {boolean} [lastCall]
2187
+ * @returns {void}
2188
+ */
2189
+ const callIterator = (context, node, jsdocNodes, state, lastCall) => {
2190
+ /* c8 ignore next -- Fallback to deprecated method */
2191
+ const {
2192
+ // @ts-expect-error ESLint < 10
2193
+ sourceCode = context.getSourceCode(),
2194
+ } = context;
2195
+ const {
2196
+ lines,
2197
+ } = sourceCode;
2198
+
2199
+ const utils = getBasicUtils(context, /** @type {Settings} */ (settings));
2200
+ for (const jsdocNode of jsdocNodes) {
2201
+ const jsdocNde = /** @type {unknown} */ (jsdocNode);
2202
+ if (!(/^\/\*\*\s/v).test(sourceCode.getText(
2203
+ /** @type {import('estree').Node} */
2204
+ (jsdocNde),
2205
+ ))) {
2206
+ continue;
2207
+ }
2208
+
2209
+ const [
2210
+ indent,
2211
+ jsdoc,
2212
+ ] = getIndentAndJSDoc(
2213
+ lines, jsdocNode,
2214
+ );
2215
+
2216
+ if (additiveCommentContexts) {
2217
+ for (const [
2218
+ idx,
2219
+ {
2220
+ comment,
2221
+ },
2222
+ ] of /** @type {ContextObject[]} */ (contexts).entries()) {
2223
+ if (comment && handler(comment, jsdoc) === false) {
2224
+ continue;
2225
+ }
2226
+
2227
+ iterate(
2228
+ {
2229
+ comment,
2230
+ lastIndex: idx,
2231
+ selector: node?.type,
2232
+ },
2233
+ indent,
2234
+ jsdoc,
2235
+ ruleConfig,
2236
+ context,
2237
+ jsdocNode,
2238
+ /** @type {Node} */
2239
+ (node),
2240
+ /** @type {Settings} */
2241
+ (settings),
2242
+ sourceCode,
2243
+ iterator,
2244
+ state,
2245
+ true,
2246
+ );
2247
+ }
2248
+
2249
+ continue;
2250
+ }
2251
+
2252
+ let lastComment;
2253
+ let lastIndex;
2254
+ // eslint-disable-next-line no-loop-func
2255
+ if (contexts && contexts.every(({
2256
+ comment,
2257
+ }, idx) => {
2258
+ lastComment = comment;
2259
+ lastIndex = idx;
2260
+
2261
+ return comment && handler(comment, jsdoc) === false;
2262
+ })) {
2263
+ continue;
2264
+ }
2265
+
2266
+ iterate(
2267
+ lastComment ? {
2268
+ comment: lastComment,
2269
+ lastIndex,
2270
+ selector: node?.type,
2271
+ } : {
2272
+ lastIndex,
2273
+ selector: node?.type,
2274
+ },
2275
+ indent,
2276
+ jsdoc,
2277
+ ruleConfig,
2278
+ context,
2279
+ jsdocNode,
2280
+ node,
2281
+ /** @type {Settings} */
2282
+ (settings),
2283
+ sourceCode,
2284
+ iterator,
2285
+ state,
2286
+ true,
2287
+ );
2288
+ }
2289
+
2290
+ const settngs = /** @type {Settings} */ (settings);
2291
+
2292
+ if (lastCall && ruleConfig.exit) {
2293
+ ruleConfig.exit({
2294
+ context,
2295
+ settings: settngs,
2296
+ state,
2297
+ utils,
2298
+ });
2299
+ }
2300
+ };
2301
+
2302
+ return {
2303
+ create (context) {
2304
+ /* c8 ignore next -- Fallback to deprecated method */
2305
+ const {
2306
+ // @ts-expect-error ESLint < 10
2307
+ sourceCode = context.getSourceCode(),
2308
+ } = context;
2309
+ settings = getSettings(context);
2310
+ if (!settings) {
2311
+ return {};
2312
+ }
2313
+
2314
+ if (contexts) {
2315
+ handler = commentHandler({
2316
+ ...settings,
2317
+ mode: settings.mode === 'permissive' ? 'typescript' : settings.mode,
2318
+ });
2319
+ }
2320
+
2321
+ const state = {};
2322
+
2323
+ return {
2324
+ /**
2325
+ * @param {import('eslint').Rule.Node} node
2326
+ * @returns {void}
2327
+ */
2328
+ '*:not(Program)' (node) {
2329
+ const commentNode = getJSDocComment(
2330
+ sourceCode, node, /** @type {Settings} */ (settings),
2331
+ );
2332
+ if (!ruleConfig.noTracking && trackedJsdocs.has(commentNode)) {
2333
+ return;
2334
+ }
2335
+
2336
+ if (!commentNode) {
2337
+ if (ruleConfig.nonComment) {
2338
+ const ste = /** @type {StateObject} */ (state);
2339
+ ruleConfig.nonComment({
2340
+ node,
2341
+ state: ste,
2342
+ });
2343
+ }
2344
+
2345
+ return;
2346
+ }
2347
+
2348
+ trackedJsdocs.add(commentNode);
2349
+ callIterator(context, node, [
2350
+ /** @type {import('estree').Comment} */
2351
+ (commentNode),
2352
+ ], /** @type {StateObject} */ (state));
2353
+ },
2354
+ 'Program:exit' () {
2355
+ const allComments = /** @type {import('estree').Comment[]} */ (
2356
+ sourceCode.getAllComments()
2357
+ );
2358
+ const untrackedJSdoc = allComments.filter((node) => {
2359
+ return !trackedJsdocs.has(node);
2360
+ });
2361
+
2362
+ callIterator(
2363
+ context,
2364
+ null,
2365
+ untrackedJSdoc,
2366
+ /** @type {StateObject} */
2367
+ (state),
2368
+ true,
2369
+ );
2370
+ },
2371
+ };
2372
+ },
2373
+ meta: ruleConfig.meta,
2374
+ };
2375
+ };
2376
+
2377
+ /**
2378
+ * Create an eslint rule that iterates over all JSDocs, regardless of whether
2379
+ * they are attached to a function-like node.
2380
+ * @param {JsdocVisitorBasic} iterator
2381
+ * @param {RuleConfig} ruleConfig
2382
+ * @returns {import('eslint').Rule.RuleModule}
2383
+ */
2384
+ const checkFile = (iterator, ruleConfig) => {
2385
+ return {
2386
+ create (context) {
2387
+ /* c8 ignore next -- Fallback to deprecated method */
2388
+ const {
2389
+ // @ts-expect-error ESLint < 10
2390
+ sourceCode = context.getSourceCode(),
2391
+ } = context;
2392
+ const settings = getSettings(context);
2393
+ if (!settings) {
2394
+ return {};
2395
+ }
2396
+
2397
+ return {
2398
+ 'Program:exit' () {
2399
+ const allComms = /** @type {unknown} */ (sourceCode.getAllComments());
2400
+ const utils = getBasicUtils(context, settings);
2401
+
2402
+ iterator({
2403
+ allComments: /** @type {import('estree').Node[]} */ (allComms),
2404
+ context,
2405
+ makeReport,
2406
+ settings,
2407
+ sourceCode,
2408
+ utils,
2409
+ });
2410
+ },
2411
+ };
2412
+ },
2413
+ meta: ruleConfig.meta,
2414
+ };
2415
+ };
2416
+
2417
+ export {
2418
+ getSettings,
2419
+ // dslint-disable-next-line unicorn/prefer-export-from -- Avoid experimental parser
2420
+
2421
+ };
2422
+
2423
+ /**
2424
+ * @param {JsdocVisitor} iterator
2425
+ * @param {RuleConfig} ruleConfig
2426
+ * @returns {import('eslint').Rule.RuleModule}
2427
+ */
2428
+ export default function iterateJsdoc (iterator, ruleConfig) {
2429
+ const metaType = ruleConfig?.meta?.type;
2430
+ if (!metaType || ![
2431
+ 'layout', 'problem', 'suggestion',
2432
+ ].includes(metaType)) {
2433
+ throw new TypeError('Rule must include `meta.type` option (with value "problem", "suggestion", or "layout")');
2434
+ }
2435
+
2436
+ if (typeof iterator !== 'function') {
2437
+ throw new TypeError('The iterator argument must be a function.');
2438
+ }
2439
+
2440
+ if (ruleConfig.checkFile) {
2441
+ return checkFile(
2442
+ /** @type {JsdocVisitorBasic} */ (iterator),
2443
+ ruleConfig,
2444
+ );
2445
+ }
2446
+
2447
+ if (ruleConfig.iterateAllJsdocs) {
2448
+ return iterateAllJsdocs(iterator, ruleConfig);
2449
+ }
2450
+
2451
+ /** @type {import('eslint').Rule.RuleModule} */
2452
+ return {
2453
+ /**
2454
+ * The entrypoint for the JSDoc rule.
2455
+ * @param {import('eslint').Rule.RuleContext} ctx
2456
+ * a reference to the context which hold all important information
2457
+ * like settings and the sourcecode to check.
2458
+ * @returns {import('eslint').Rule.RuleListener}
2459
+ * a listener with parser callback function.
2460
+ */
2461
+ create (ctx) {
2462
+ const context = ruleConfig.modifyContext ?
2463
+ ruleConfig.modifyContext(ctx) :
2464
+ ctx;
2465
+
2466
+ const settings = getSettings(context);
2467
+ if (!settings) {
2468
+ return {};
2469
+ }
2470
+
2471
+ /**
2472
+ * @type {Context[]|undefined}
2473
+ */
2474
+ let contexts;
2475
+ if (ruleConfig.contextDefaults || ruleConfig.contextSelected || ruleConfig.matchContext) {
2476
+ contexts = ruleConfig.matchContext && context.options[0]?.match ?
2477
+ context.options[0].match :
2478
+ jsdocUtils.enforcedContexts(context, ruleConfig.contextDefaults, ruleConfig.nonGlobalSettings ? {} : settings);
2479
+
2480
+ if (contexts) {
2481
+ contexts = contexts.map((obj) => {
2482
+ if (typeof obj === 'object' && !obj.context) {
2483
+ return {
2484
+ ...obj,
2485
+ context: 'any',
2486
+ };
2487
+ }
2488
+
2489
+ return obj;
2490
+ });
2491
+ }
2492
+
2493
+ const hasPlainAny = contexts?.includes('any');
2494
+ const hasObjectAny = !hasPlainAny && contexts?.find((ctxt) => {
2495
+ if (typeof ctxt === 'string') {
2496
+ return false;
2497
+ }
2498
+
2499
+ return ctxt?.context === 'any';
2500
+ });
2501
+ if (hasPlainAny || hasObjectAny) {
2502
+ return iterateAllJsdocs(
2503
+ iterator,
2504
+ ruleConfig,
2505
+ hasObjectAny ? /** @type {ContextObject[]} */ (contexts) : null,
2506
+ ruleConfig.matchContext,
2507
+ ).create(context);
2508
+ }
2509
+ }
2510
+
2511
+ /* c8 ignore next -- Fallback to deprecated method */
2512
+ const {
2513
+ // @ts-expect-error ESLint < 10
2514
+ sourceCode = context.getSourceCode(),
2515
+ } = context;
2516
+ const {
2517
+ lines,
2518
+ } = sourceCode;
2519
+
2520
+ /** @type {Partial<StateObject>} */
2521
+ const state = {};
2522
+
2523
+ /** @type {CheckJsdoc} */
2524
+ const checkJsdoc = (info, handler, node) => {
2525
+ const jsdocNode = getJSDocComment(sourceCode, node, settings);
2526
+ if (!jsdocNode) {
2527
+ return;
2528
+ }
2529
+
2530
+ const [
2531
+ indent,
2532
+ jsdoc,
2533
+ ] = getIndentAndJSDoc(
2534
+ lines,
2535
+ /** @type {import('estree').Comment} */
2536
+ (jsdocNode),
2537
+ );
2538
+
2539
+ if (
2540
+ // Note, `handler` should already be bound in its first argument
2541
+ // with these only to be called after the value of
2542
+ // `comment`
2543
+ handler && handler(jsdoc) === false
2544
+ ) {
2545
+ return;
2546
+ }
2547
+
2548
+ iterate(
2549
+ info,
2550
+ indent,
2551
+ jsdoc,
2552
+ ruleConfig,
2553
+ context,
2554
+ jsdocNode,
2555
+ node,
2556
+ settings,
2557
+ sourceCode,
2558
+ iterator,
2559
+ /** @type {StateObject} */
2560
+ (state),
2561
+ );
2562
+ };
2563
+
2564
+ /** @type {import('eslint').Rule.RuleListener} */
2565
+ let contextObject = {};
2566
+
2567
+ if (contexts && (
2568
+ ruleConfig.contextDefaults || ruleConfig.contextSelected || ruleConfig.matchContext
2569
+ )) {
2570
+ contextObject = jsdocUtils.getContextObject(
2571
+ contexts,
2572
+ checkJsdoc,
2573
+ commentHandler({
2574
+ ...settings,
2575
+ mode: settings.mode === 'permissive' ? 'typescript' : settings.mode,
2576
+ }),
2577
+ );
2578
+ } else {
2579
+ for (const prop of [
2580
+ 'ArrowFunctionExpression',
2581
+ 'FunctionDeclaration',
2582
+ 'FunctionExpression',
2583
+ 'TSDeclareFunction',
2584
+ ]) {
2585
+ contextObject[prop] = checkJsdoc.bind(null, {
2586
+ selector: prop,
2587
+ }, null);
2588
+ }
2589
+ }
2590
+
2591
+ if (typeof ruleConfig.exit === 'function') {
2592
+ contextObject['Program:exit'] = () => {
2593
+ const ste = /** @type {StateObject} */ (state);
2594
+
2595
+ // @ts-expect-error `utils` not needed at this point
2596
+ /** @type {Required<RuleConfig>} */ (ruleConfig).exit({
2597
+ context,
2598
+ settings,
2599
+ state: ste,
2600
+ });
2601
+ };
2602
+ }
2603
+
2604
+ return contextObject;
2605
+ },
2606
+ meta: ruleConfig.meta,
2607
+ };
2608
+ }
2609
+
2610
+ export {
2611
+ parseComment,
2612
+ } from '@es-joy/jsdoccomment';