eslint-plugin-jsdoc 63.3.3 → 64.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/package.json +23 -48
  2. package/src/index.js +3 -6
  3. package/dist/WarnSettings.cjs +0 -38
  4. package/dist/WarnSettings.cjs.map +0 -1
  5. package/dist/alignTransform.cjs +0 -402
  6. package/dist/alignTransform.cjs.map +0 -1
  7. package/dist/buildForbidRuleDefinition.cjs +0 -101
  8. package/dist/buildForbidRuleDefinition.cjs.map +0 -1
  9. package/dist/buildRejectOrPreferRuleDefinition.cjs +0 -352
  10. package/dist/buildRejectOrPreferRuleDefinition.cjs.map +0 -1
  11. package/dist/cjs/WarnSettings.d.ts +0 -16
  12. package/dist/cjs/alignTransform.d.ts +0 -33
  13. package/dist/cjs/buildForbidRuleDefinition.d.ts +0 -14
  14. package/dist/cjs/buildRejectOrPreferRuleDefinition.d.ts +0 -8
  15. package/dist/cjs/defaultTagOrder.d.ts +0 -4
  16. package/dist/cjs/exportParser.d.ts +0 -40
  17. package/dist/cjs/getDefaultTagStructureForMode.d.ts +0 -10
  18. package/dist/cjs/getJsdocProcessorPlugin.d.cts +0 -5
  19. package/dist/cjs/getJsdocProcessorPlugin.d.ts +0 -66
  20. package/dist/cjs/index-cjs.d.ts +0 -26
  21. package/dist/cjs/index.cjs.d.cts +0 -2
  22. package/dist/cjs/iterateJsdoc.d.cts +0 -7
  23. package/dist/cjs/iterateJsdoc.d.ts +0 -495
  24. package/dist/cjs/jsdocUtils.d.ts +0 -500
  25. package/dist/cjs/rules/checkAccess.d.ts +0 -2
  26. package/dist/cjs/rules/checkAlignment.d.ts +0 -2
  27. package/dist/cjs/rules/checkExamples.d.ts +0 -3
  28. package/dist/cjs/rules/checkIndentation.d.ts +0 -2
  29. package/dist/cjs/rules/checkLineAlignment.d.ts +0 -9
  30. package/dist/cjs/rules/checkParamNames.d.ts +0 -2
  31. package/dist/cjs/rules/checkPropertyNames.d.ts +0 -2
  32. package/dist/cjs/rules/checkSyntax.d.ts +0 -2
  33. package/dist/cjs/rules/checkTagNames.d.ts +0 -2
  34. package/dist/cjs/rules/checkTemplateNames.d.ts +0 -2
  35. package/dist/cjs/rules/checkTypes.d.ts +0 -7
  36. package/dist/cjs/rules/checkValues.d.ts +0 -2
  37. package/dist/cjs/rules/convertToJsdocComments.d.ts +0 -266
  38. package/dist/cjs/rules/emptyTags.d.ts +0 -2
  39. package/dist/cjs/rules/escapeInlineTags.d.ts +0 -2
  40. package/dist/cjs/rules/implementsOnClasses.d.ts +0 -2
  41. package/dist/cjs/rules/importsAsDependencies.d.ts +0 -2
  42. package/dist/cjs/rules/informativeDocs.d.ts +0 -2
  43. package/dist/cjs/rules/linesBeforeBlock.d.ts +0 -2
  44. package/dist/cjs/rules/matchDescription.d.ts +0 -2
  45. package/dist/cjs/rules/matchName.d.ts +0 -2
  46. package/dist/cjs/rules/multilineBlocks.d.ts +0 -2
  47. package/dist/cjs/rules/noBadBlocks.d.ts +0 -2
  48. package/dist/cjs/rules/noBlankBlockDescriptions.d.ts +0 -2
  49. package/dist/cjs/rules/noBlankBlocks.d.ts +0 -2
  50. package/dist/cjs/rules/noDefaults.d.ts +0 -2
  51. package/dist/cjs/rules/noMissingSyntax.d.ts +0 -9
  52. package/dist/cjs/rules/noMultiAsterisks.d.ts +0 -2
  53. package/dist/cjs/rules/noRestrictedSyntax.d.ts +0 -2
  54. package/dist/cjs/rules/noTypes.d.ts +0 -2
  55. package/dist/cjs/rules/noUndefinedTypes.d.ts +0 -2
  56. package/dist/cjs/rules/normalizeSeeLinks.d.ts +0 -2
  57. package/dist/cjs/rules/preferImportTag.d.ts +0 -2
  58. package/dist/cjs/rules/requireAsteriskPrefix.d.ts +0 -2
  59. package/dist/cjs/rules/requireDescription.d.ts +0 -2
  60. package/dist/cjs/rules/requireDescriptionCompleteSentence.d.ts +0 -2
  61. package/dist/cjs/rules/requireExample.d.ts +0 -2
  62. package/dist/cjs/rules/requireFileOverview.d.ts +0 -2
  63. package/dist/cjs/rules/requireHyphenBeforeParamDescription.d.ts +0 -2
  64. package/dist/cjs/rules/requireJsdoc.d.ts +0 -24
  65. package/dist/cjs/rules/requireParam.d.ts +0 -3
  66. package/dist/cjs/rules/requireParamDescription.d.ts +0 -2
  67. package/dist/cjs/rules/requireParamName.d.ts +0 -2
  68. package/dist/cjs/rules/requireParamType.d.ts +0 -2
  69. package/dist/cjs/rules/requireProperty.d.ts +0 -2
  70. package/dist/cjs/rules/requirePropertyDescription.d.ts +0 -2
  71. package/dist/cjs/rules/requirePropertyName.d.ts +0 -2
  72. package/dist/cjs/rules/requirePropertyType.d.ts +0 -2
  73. package/dist/cjs/rules/requireRejects.d.ts +0 -2
  74. package/dist/cjs/rules/requireReturns.d.ts +0 -2
  75. package/dist/cjs/rules/requireReturnsCheck.d.ts +0 -2
  76. package/dist/cjs/rules/requireReturnsDescription.d.ts +0 -2
  77. package/dist/cjs/rules/requireReturnsType.d.ts +0 -2
  78. package/dist/cjs/rules/requireTags.d.ts +0 -2
  79. package/dist/cjs/rules/requireTemplate.d.ts +0 -2
  80. package/dist/cjs/rules/requireThrows.d.ts +0 -2
  81. package/dist/cjs/rules/requireYields.d.ts +0 -2
  82. package/dist/cjs/rules/requireYieldsCheck.d.ts +0 -2
  83. package/dist/cjs/rules/sortTags.d.ts +0 -2
  84. package/dist/cjs/rules/tagLines.d.ts +0 -2
  85. package/dist/cjs/rules/textEscaping.d.ts +0 -2
  86. package/dist/cjs/rules/tsMethodSignatureStyle.d.ts +0 -2
  87. package/dist/cjs/rules/tsNoEmptyObjectType.d.ts +0 -2
  88. package/dist/cjs/rules/tsNoUnnecessaryTemplateExpression.d.ts +0 -2
  89. package/dist/cjs/rules/tsPreferFunctionType.d.ts +0 -2
  90. package/dist/cjs/rules/typeFormatting.d.ts +0 -2
  91. package/dist/cjs/rules/validTypes.d.ts +0 -2
  92. package/dist/cjs/tagNames.d.ts +0 -15
  93. package/dist/cjs/utils/hasReturnValue.d.ts +0 -19
  94. package/dist/defaultTagOrder.cjs +0 -46
  95. package/dist/defaultTagOrder.cjs.map +0 -1
  96. package/dist/exportParser.cjs +0 -732
  97. package/dist/exportParser.cjs.map +0 -1
  98. package/dist/generateDocs.cjs +0 -342
  99. package/dist/generateDocs.cjs.map +0 -1
  100. package/dist/generateOptions.cjs +0 -62
  101. package/dist/generateOptions.cjs.map +0 -1
  102. package/dist/generateRule.cjs +0 -248
  103. package/dist/generateRule.cjs.map +0 -1
  104. package/dist/generateRuleTypes.cjs +0 -24
  105. package/dist/generateRuleTypes.cjs.map +0 -1
  106. package/dist/getDefaultTagStructureForMode.cjs +0 -289
  107. package/dist/getDefaultTagStructureForMode.cjs.map +0 -1
  108. package/dist/getJsdocProcessorPlugin.cjs +0 -587
  109. package/dist/getJsdocProcessorPlugin.cjs.map +0 -1
  110. package/dist/getJsdocProcessorPlugin.cts +0 -5
  111. package/dist/index-cjs.cjs +0 -600
  112. package/dist/index-cjs.cjs.map +0 -1
  113. package/dist/index-cjs.d.ts +0 -27
  114. package/dist/index-esm.cjs +0 -162
  115. package/dist/index-esm.cjs.map +0 -1
  116. package/dist/index-esm.d.ts +0 -72
  117. package/dist/index.cjs +0 -748
  118. package/dist/index.cjs.cts +0 -3
  119. package/dist/index.cjs.map +0 -1
  120. package/dist/iterateJsdoc.cjs +0 -2150
  121. package/dist/iterateJsdoc.cjs.map +0 -1
  122. package/dist/iterateJsdoc.cts +0 -7
  123. package/dist/jsdocUtils.cjs +0 -1786
  124. package/dist/jsdocUtils.cjs.map +0 -1
  125. package/dist/rules/checkAccess.cjs +0 -40
  126. package/dist/rules/checkAccess.cjs.map +0 -1
  127. package/dist/rules/checkAlignment.cjs +0 -78
  128. package/dist/rules/checkAlignment.cjs.map +0 -1
  129. package/dist/rules/checkExamples.cjs +0 -521
  130. package/dist/rules/checkExamples.cjs.map +0 -1
  131. package/dist/rules/checkIndentation.cjs +0 -170
  132. package/dist/rules/checkIndentation.cjs.map +0 -1
  133. package/dist/rules/checkLineAlignment.cjs +0 -398
  134. package/dist/rules/checkLineAlignment.cjs.map +0 -1
  135. package/dist/rules/checkParamNames.cjs +0 -407
  136. package/dist/rules/checkParamNames.cjs.map +0 -1
  137. package/dist/rules/checkPropertyNames.cjs +0 -135
  138. package/dist/rules/checkPropertyNames.cjs.map +0 -1
  139. package/dist/rules/checkSyntax.cjs +0 -38
  140. package/dist/rules/checkSyntax.cjs.map +0 -1
  141. package/dist/rules/checkTagNames.cjs +0 -312
  142. package/dist/rules/checkTagNames.cjs.map +0 -1
  143. package/dist/rules/checkTemplateNames.cjs +0 -192
  144. package/dist/rules/checkTemplateNames.cjs.map +0 -1
  145. package/dist/rules/checkTypes.cjs +0 -111
  146. package/dist/rules/checkTypes.cjs.map +0 -1
  147. package/dist/rules/checkValues.cjs +0 -166
  148. package/dist/rules/checkValues.cjs.map +0 -1
  149. package/dist/rules/convertToJsdocComments.cjs +0 -356
  150. package/dist/rules/convertToJsdocComments.cjs.map +0 -1
  151. package/dist/rules/emptyTags.cjs +0 -98
  152. package/dist/rules/emptyTags.cjs.map +0 -1
  153. package/dist/rules/escapeInlineTags.cjs +0 -234
  154. package/dist/rules/escapeInlineTags.cjs.map +0 -1
  155. package/dist/rules/implementsOnClasses.cjs +0 -74
  156. package/dist/rules/implementsOnClasses.cjs.map +0 -1
  157. package/dist/rules/importsAsDependencies.cjs +0 -104
  158. package/dist/rules/importsAsDependencies.cjs.map +0 -1
  159. package/dist/rules/informativeDocs.cjs +0 -187
  160. package/dist/rules/informativeDocs.cjs.map +0 -1
  161. package/dist/rules/linesBeforeBlock.cjs +0 -120
  162. package/dist/rules/linesBeforeBlock.cjs.map +0 -1
  163. package/dist/rules/matchDescription.cjs +0 -356
  164. package/dist/rules/matchDescription.cjs.map +0 -1
  165. package/dist/rules/matchName.cjs +0 -160
  166. package/dist/rules/matchName.cjs.map +0 -1
  167. package/dist/rules/multilineBlocks.cjs +0 -431
  168. package/dist/rules/multilineBlocks.cjs.map +0 -1
  169. package/dist/rules/noBadBlocks.cjs +0 -100
  170. package/dist/rules/noBadBlocks.cjs.map +0 -1
  171. package/dist/rules/noBlankBlockDescriptions.cjs +0 -63
  172. package/dist/rules/noBlankBlockDescriptions.cjs.map +0 -1
  173. package/dist/rules/noBlankBlocks.cjs +0 -54
  174. package/dist/rules/noBlankBlocks.cjs.map +0 -1
  175. package/dist/rules/noDefaults.cjs +0 -102
  176. package/dist/rules/noDefaults.cjs.map +0 -1
  177. package/dist/rules/noMissingSyntax.cjs +0 -196
  178. package/dist/rules/noMissingSyntax.cjs.map +0 -1
  179. package/dist/rules/noMultiAsterisks.cjs +0 -126
  180. package/dist/rules/noMultiAsterisks.cjs.map +0 -1
  181. package/dist/rules/noRestrictedSyntax.cjs +0 -68
  182. package/dist/rules/noRestrictedSyntax.cjs.map +0 -1
  183. package/dist/rules/noTypes.cjs +0 -101
  184. package/dist/rules/noTypes.cjs.map +0 -1
  185. package/dist/rules/noUndefinedTypes.cjs +0 -616
  186. package/dist/rules/noUndefinedTypes.cjs.map +0 -1
  187. package/dist/rules/normalizeSeeLinks.cjs +0 -271
  188. package/dist/rules/normalizeSeeLinks.cjs.map +0 -1
  189. package/dist/rules/preferImportTag.cjs +0 -362
  190. package/dist/rules/preferImportTag.cjs.map +0 -1
  191. package/dist/rules/requireAsteriskPrefix.cjs +0 -190
  192. package/dist/rules/requireAsteriskPrefix.cjs.map +0 -1
  193. package/dist/rules/requireDescription.cjs +0 -164
  194. package/dist/rules/requireDescription.cjs.map +0 -1
  195. package/dist/rules/requireDescriptionCompleteSentence.cjs +0 -321
  196. package/dist/rules/requireDescriptionCompleteSentence.cjs.map +0 -1
  197. package/dist/rules/requireExample.cjs +0 -136
  198. package/dist/rules/requireExample.cjs.map +0 -1
  199. package/dist/rules/requireFileOverview.cjs +0 -194
  200. package/dist/rules/requireFileOverview.cjs.map +0 -1
  201. package/dist/rules/requireHyphenBeforeParamDescription.cjs +0 -166
  202. package/dist/rules/requireHyphenBeforeParamDescription.cjs.map +0 -1
  203. package/dist/rules/requireJsdoc.cjs +0 -721
  204. package/dist/rules/requireJsdoc.cjs.map +0 -1
  205. package/dist/rules/requireParam.cjs +0 -772
  206. package/dist/rules/requireParam.cjs.map +0 -1
  207. package/dist/rules/requireParamDescription.cjs +0 -105
  208. package/dist/rules/requireParamDescription.cjs.map +0 -1
  209. package/dist/rules/requireParamName.cjs +0 -68
  210. package/dist/rules/requireParamName.cjs.map +0 -1
  211. package/dist/rules/requireParamType.cjs +0 -104
  212. package/dist/rules/requireParamType.cjs.map +0 -1
  213. package/dist/rules/requireProperty.cjs +0 -63
  214. package/dist/rules/requireProperty.cjs.map +0 -1
  215. package/dist/rules/requirePropertyDescription.cjs +0 -29
  216. package/dist/rules/requirePropertyDescription.cjs.map +0 -1
  217. package/dist/rules/requirePropertyName.cjs +0 -29
  218. package/dist/rules/requirePropertyName.cjs.map +0 -1
  219. package/dist/rules/requirePropertyType.cjs +0 -29
  220. package/dist/rules/requirePropertyType.cjs.map +0 -1
  221. package/dist/rules/requireRejects.cjs +0 -226
  222. package/dist/rules/requireRejects.cjs.map +0 -1
  223. package/dist/rules/requireReturns.cjs +0 -262
  224. package/dist/rules/requireReturns.cjs.map +0 -1
  225. package/dist/rules/requireReturnsCheck.cjs +0 -225
  226. package/dist/rules/requireReturnsCheck.cjs.map +0 -1
  227. package/dist/rules/requireReturnsDescription.cjs +0 -72
  228. package/dist/rules/requireReturnsDescription.cjs.map +0 -1
  229. package/dist/rules/requireReturnsType.cjs +0 -68
  230. package/dist/rules/requireReturnsType.cjs.map +0 -1
  231. package/dist/rules/requireTags.cjs +0 -74
  232. package/dist/rules/requireTags.cjs.map +0 -1
  233. package/dist/rules/requireTemplate.cjs +0 -220
  234. package/dist/rules/requireTemplate.cjs.map +0 -1
  235. package/dist/rules/requireThrows.cjs +0 -118
  236. package/dist/rules/requireThrows.cjs.map +0 -1
  237. package/dist/rules/requireYields.cjs +0 -224
  238. package/dist/rules/requireYields.cjs.map +0 -1
  239. package/dist/rules/requireYieldsCheck.cjs +0 -179
  240. package/dist/rules/requireYieldsCheck.cjs.map +0 -1
  241. package/dist/rules/sortTags.cjs +0 -656
  242. package/dist/rules/sortTags.cjs.map +0 -1
  243. package/dist/rules/tagLines.cjs +0 -374
  244. package/dist/rules/tagLines.cjs.map +0 -1
  245. package/dist/rules/textEscaping.cjs +0 -141
  246. package/dist/rules/textEscaping.cjs.map +0 -1
  247. package/dist/rules/tsMethodSignatureStyle.cjs +0 -240
  248. package/dist/rules/tsMethodSignatureStyle.cjs.map +0 -1
  249. package/dist/rules/tsNoEmptyObjectType.cjs +0 -62
  250. package/dist/rules/tsNoEmptyObjectType.cjs.map +0 -1
  251. package/dist/rules/tsNoUnnecessaryTemplateExpression.cjs +0 -104
  252. package/dist/rules/tsNoUnnecessaryTemplateExpression.cjs.map +0 -1
  253. package/dist/rules/tsPreferFunctionType.cjs +0 -110
  254. package/dist/rules/tsPreferFunctionType.cjs.map +0 -1
  255. package/dist/rules/typeFormatting.cjs +0 -607
  256. package/dist/rules/typeFormatting.cjs.map +0 -1
  257. package/dist/rules/validTypes.cjs +0 -324
  258. package/dist/rules/validTypes.cjs.map +0 -1
  259. package/dist/tagNames.cjs +0 -244
  260. package/dist/tagNames.cjs.map +0 -1
  261. package/dist/to-valid-identifier.cjs +0 -263
  262. package/dist/utils/hasReturnValue.cjs +0 -495
  263. package/dist/utils/hasReturnValue.cjs.map +0 -1
  264. package/rollup.config.js +0 -16
  265. package/src/getJsdocProcessorPlugin.cts +0 -5
  266. package/src/index-cjs.js +0 -760
  267. package/src/index-esm.js +0 -196
  268. package/src/index.cjs.cts +0 -3
  269. package/src/iterateJsdoc.cts +0 -7
@@ -1,1786 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.hasParams = exports.hasATag = exports.getTagsByType = exports.getTags = exports.getTagStructureForMode = exports.getTagDescription = exports.getRegexFromString = exports.getPreferredTagNameSimple = exports.getPreferredTagName = exports.getJsdocTagsDeep = exports.getJSDocCommentBlocks = exports.getInlineTags = exports.getIndent = exports.getFunctionParameterNames = exports.getDocumentNamepathDefiningTags = exports.getContextObject = exports.getAllTags = exports.forEachPreferredTag = exports.flattenRoots = exports.filterTags = exports.exemptSpeciaMethods = exports.enforcedContexts = exports.dropPathSegmentQuotes = exports.comparePaths = void 0;
7
- Object.defineProperty(exports, "hasReturnValue", {
8
- enumerable: true,
9
- get: function () {
10
- return _hasReturnValue.hasReturnValue;
11
- }
12
- });
13
- exports.hasThrowValue = exports.hasTag = void 0;
14
- Object.defineProperty(exports, "hasValueOrExecutorHasNonEmptyResolveValue", {
15
- enumerable: true,
16
- get: function () {
17
- return _hasReturnValue.hasValueOrExecutorHasNonEmptyResolveValue;
18
- }
19
- });
20
- exports.tagMustHaveTypePosition = exports.tagMustHaveNamePosition = exports.tagMissingRequiredTypeOrNamepath = exports.tagMightHaveTypePosition = exports.tagMightHaveNamepath = exports.tagMightHaveNamePosition = exports.tagMightHaveNameOrNamepath = exports.tagMightHaveName = exports.tagMightHaveEitherTypeOrNamePosition = exports.strictNativeTypes = exports.setTagStructure = exports.rewireByParsedType = exports.pathDoesNotBeginWith = exports.parseClosureTemplateTag = exports.overrideTagStructure = exports.mayBeUndefinedTypeTag = exports.isValidTag = exports.isSetter = exports.isNamepathReferencingTag = exports.isNamepathOrUrlReferencingTag = exports.isNameOrNamepathDefiningTag = exports.isGetter = exports.isConstructor = exports.hasYieldValue = void 0;
21
- var _getDefaultTagStructureForMode = _interopRequireDefault(require("./getDefaultTagStructureForMode.cjs"));
22
- var _tagNames = require("./tagNames.cjs");
23
- var _WarnSettings = _interopRequireDefault(require("./WarnSettings.cjs"));
24
- var _jsdoccomment = require("@es-joy/jsdoccomment");
25
- var _hasReturnValue = require("./utils/hasReturnValue.cjs");
26
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
27
- /**
28
- * @typedef {number} Integer
29
- */
30
- /**
31
- * @typedef {import('./utils/hasReturnValue.js').ESTreeOrTypeScriptNode} ESTreeOrTypeScriptNode
32
- */
33
-
34
- /**
35
- * @typedef {"jsdoc"|"typescript"|"closure"|"permissive"} ParserMode
36
- */
37
-
38
- /**
39
- * @type {import('./getDefaultTagStructureForMode.js').TagStructure}
40
- */
41
- let tagStructure;
42
-
43
- /**
44
- * @param {ParserMode} mode
45
- * @returns {void}
46
- */
47
- const setTagStructure = mode => {
48
- tagStructure = (0, _getDefaultTagStructureForMode.default)(mode);
49
- };
50
-
51
- /**
52
- * @typedef {undefined|string|{
53
- * name: Integer,
54
- * restElement: boolean
55
- * }|{
56
- * isRestProperty: boolean|undefined,
57
- * name: string,
58
- * restElement: boolean
59
- * }|{
60
- * name: string,
61
- * restElement: boolean
62
- * }} ParamCommon
63
- */
64
- /**
65
- * @typedef {ParamCommon|[string|undefined, (FlattendRootInfo & {
66
- * annotationParamName?: string,
67
- * })]|NestedParamInfo} ParamNameInfo
68
- */
69
-
70
- /**
71
- * @typedef {{
72
- * hasPropertyRest: boolean,
73
- * hasRestElement: boolean,
74
- * names: string[],
75
- * rests: boolean[],
76
- * }} FlattendRootInfo
77
- */
78
- /**
79
- * @typedef {[string, (string[]|ParamInfo[])]} NestedParamInfo
80
- */
81
- /**
82
- * @typedef {ParamCommon|
83
- * [string|undefined, (FlattendRootInfo & {
84
- * annotationParamName?: string
85
- * })]|
86
- * NestedParamInfo} ParamInfo
87
- */
88
-
89
- /**
90
- * Given a nested array of property names, reduce them to a single array,
91
- * appending the name of the root element along the way if present.
92
- * @callback FlattenRoots
93
- * @param {ParamInfo[]} params
94
- * @param {string} [root]
95
- * @returns {FlattendRootInfo}
96
- */
97
-
98
- /** @type {FlattenRoots} */
99
- exports.setTagStructure = setTagStructure;
100
- const flattenRoots = (params, root = '') => {
101
- let hasRestElement = false;
102
- let hasPropertyRest = false;
103
-
104
- /**
105
- * @type {boolean[]}
106
- */
107
- const rests = [];
108
- const names = params.reduce(
109
- /**
110
- * @param {string[]} acc
111
- * @param {ParamInfo} cur
112
- * @returns {string[]}
113
- */
114
- (acc, cur) => {
115
- if (Array.isArray(cur)) {
116
- let nms;
117
- if (Array.isArray(cur[1])) {
118
- nms = cur[1];
119
- } else {
120
- if (cur[1].hasRestElement) {
121
- hasRestElement = true;
122
- }
123
- if (cur[1].hasPropertyRest) {
124
- hasPropertyRest = true;
125
- }
126
- nms = cur[1].names;
127
- }
128
- const flattened = flattenRoots(nms, root ? `${root}.${cur[0]}` : cur[0]);
129
- if (flattened.hasRestElement) {
130
- hasRestElement = true;
131
- }
132
- if (flattened.hasPropertyRest) {
133
- hasPropertyRest = true;
134
- }
135
- const inner = /** @type {string[]} */[root ? `${root}.${cur[0]}` : cur[0], ...flattened.names].filter(Boolean);
136
- rests.push(false, ...flattened.rests);
137
- return acc.concat(inner);
138
- }
139
- if (typeof cur === 'object') {
140
- if ('isRestProperty' in cur && cur.isRestProperty) {
141
- hasPropertyRest = true;
142
- rests.push(true);
143
- } else {
144
- rests.push(false);
145
- }
146
- if ('restElement' in cur && cur.restElement) {
147
- hasRestElement = true;
148
- }
149
- acc.push(root ? `${root}.${String(cur.name)}` : String(cur.name));
150
- } else if (typeof cur !== 'undefined') {
151
- rests.push(false);
152
- acc.push(root ? `${root}.${cur}` : cur);
153
- }
154
- return acc;
155
- }, []);
156
- return {
157
- hasPropertyRest,
158
- hasRestElement,
159
- names,
160
- rests
161
- };
162
- };
163
-
164
- /**
165
- * @param {import('@typescript-eslint/types').TSESTree.TSIndexSignature|
166
- * import('@typescript-eslint/types').TSESTree.TSConstructSignatureDeclaration|
167
- * import('@typescript-eslint/types').TSESTree.TSCallSignatureDeclaration|
168
- * import('@typescript-eslint/types').TSESTree.TSPropertySignature} propSignature
169
- * @returns {undefined|string|[string, string[]]}
170
- */
171
- exports.flattenRoots = flattenRoots;
172
- const getPropertiesFromPropertySignature = propSignature => {
173
- if (propSignature.type === 'TSIndexSignature' || propSignature.type === 'TSConstructSignatureDeclaration' || propSignature.type === 'TSCallSignatureDeclaration') {
174
- return undefined;
175
- }
176
- if (propSignature.typeAnnotation && propSignature.typeAnnotation.typeAnnotation.type === 'TSTypeLiteral') {
177
- return [/** @type {import('@typescript-eslint/types').TSESTree.Identifier} */propSignature.key.name, propSignature.typeAnnotation.typeAnnotation.members.map(member => {
178
- return /** @type {string} */getPropertiesFromPropertySignature(/** @type {import('@typescript-eslint/types').TSESTree.TSPropertySignature} */
179
- member);
180
- })];
181
- }
182
- return /** @type {import('@typescript-eslint/types').TSESTree.Identifier} */propSignature.key.name;
183
- };
184
-
185
- /**
186
- * @param {ESTreeOrTypeScriptNode|null} functionNode
187
- * @param {boolean} [checkDefaultObjects]
188
- * @param {boolean} [ignoreInterfacedParameters]
189
- * @throws {Error}
190
- * @returns {ParamNameInfo[]}
191
- */
192
- const getFunctionParameterNames = (functionNode, checkDefaultObjects, ignoreInterfacedParameters) => {
193
- /* eslint-disable complexity -- Temporary */
194
- /**
195
- * @param {import('estree').Identifier|import('estree').AssignmentPattern|
196
- * import('estree').ObjectPattern|import('estree').Property|
197
- * import('estree').RestElement|import('estree').ArrayPattern|
198
- * import('@typescript-eslint/types').TSESTree.TSParameterProperty|
199
- * import('@typescript-eslint/types').TSESTree.Property|
200
- * import('@typescript-eslint/types').TSESTree.RestElement|
201
- * import('@typescript-eslint/types').TSESTree.Identifier|
202
- * import('@typescript-eslint/types').TSESTree.ObjectPattern|
203
- * import('@typescript-eslint/types').TSESTree.BindingName|
204
- * import('@typescript-eslint/types').TSESTree.Parameter
205
- * } param
206
- * @param {boolean} [isProperty]
207
- * @returns {ParamNameInfo|[string, ParamNameInfo[]]}
208
- */
209
- const getParamName = (param, isProperty) => {
210
- /* eslint-enable complexity -- Temporary */
211
- const hasLeftTypeAnnotation = 'left' in param && 'typeAnnotation' in param.left;
212
- if ('typeAnnotation' in param || hasLeftTypeAnnotation) {
213
- if (ignoreInterfacedParameters && 'typeAnnotation' in param && param.typeAnnotation) {
214
- // No-op
215
- return [undefined, {
216
- hasPropertyRest: false,
217
- hasRestElement: false,
218
- names: [],
219
- rests: []
220
- }];
221
- }
222
- const typeAnnotation = hasLeftTypeAnnotation ? /** @type {import('@typescript-eslint/types').TSESTree.Identifier} */param.left.typeAnnotation : /** @type {import('@typescript-eslint/types').TSESTree.Identifier|import('@typescript-eslint/types').TSESTree.ObjectPattern} */
223
- param.typeAnnotation;
224
- if (typeAnnotation?.typeAnnotation?.type === 'TSTypeLiteral') {
225
- const propertyNames = typeAnnotation.typeAnnotation.members.map(member => {
226
- return getPropertiesFromPropertySignature(/** @type {import('@typescript-eslint/types').TSESTree.TSPropertySignature} */
227
- member);
228
- });
229
- const flattened = {
230
- ...flattenRoots(propertyNames),
231
- annotationParamName: 'name' in param ? param.name : undefined
232
- };
233
- const hasLeftName = 'left' in param && 'name' in param.left;
234
- if ('name' in param || hasLeftName) {
235
- return [hasLeftName ? /** @type {import('@typescript-eslint/types').TSESTree.Identifier} */param.left.name : /** @type {import('@typescript-eslint/types').TSESTree.Identifier} */param.name, flattened];
236
- }
237
- return [undefined, flattened];
238
- }
239
- }
240
- if ('name' in param) {
241
- return param.name;
242
- }
243
- if ('left' in param && 'name' in param.left) {
244
- return param.left.name;
245
- }
246
- if (param.type === 'ObjectPattern' || 'left' in param && param.left.type === 'ObjectPattern') {
247
- const properties = /** @type {import('@typescript-eslint/types').TSESTree.ObjectPattern} */param.properties || /** @type {import('estree').ObjectPattern} */
248
- (/** @type {import('@typescript-eslint/types').TSESTree.AssignmentPattern} */param.left)?.properties;
249
- const roots = properties.map(prop => {
250
- return getParamName(prop, true);
251
- });
252
- return [undefined, flattenRoots(roots)];
253
- }
254
- if (param.type === 'Property') {
255
- switch (param.value.type) {
256
- case 'ArrayPattern':
257
- {
258
- return [/** @type {import('estree').Identifier} */
259
- param.key.name, /** @type {import('estree').ArrayPattern} */param.value.elements.map((prop, idx) => {
260
- return {
261
- name: idx,
262
- restElement: prop?.type === 'RestElement'
263
- };
264
- })];
265
- }
266
- case 'ObjectPattern':
267
- {
268
- return [/** @type {import('estree').Identifier} */param.key.name, /** @type {import('estree').ObjectPattern} */param.value.properties.map(prop => {
269
- return /** @type {string|[string, string[]]} */getParamName(prop, isProperty);
270
- })];
271
- }
272
- case 'AssignmentPattern':
273
- {
274
- switch (param.value.left.type) {
275
- case 'ArrayPattern':
276
- return [/** @type {import('estree').Identifier} */
277
- param.key.name, /** @type {import('estree').ArrayPattern} */param.value.left.elements.map((prop, idx) => {
278
- return {
279
- name: idx,
280
- restElement: prop?.type === 'RestElement'
281
- };
282
- })];
283
- case 'Identifier':
284
- // Default parameter
285
- if (checkDefaultObjects && param.value.right.type === 'ObjectExpression') {
286
- return [/** @type {import('estree').Identifier} */param.key.name, /** @type {import('estree').AssignmentPattern} */param.value.right.properties.map(prop => {
287
- return /** @type {string} */getParamName(/** @type {import('estree').Property} */
288
- prop, isProperty);
289
- })];
290
- }
291
- break;
292
- case 'ObjectPattern':
293
- return [/** @type {import('estree').Identifier} */
294
- param.key.name, /** @type {import('estree').ObjectPattern} */param.value.left.properties.map(prop => {
295
- return getParamName(prop, isProperty);
296
- })];
297
- }
298
- }
299
- }
300
- switch (param.key.type) {
301
- case 'Identifier':
302
- return param.key.name;
303
-
304
- // The key of an object could also be a string or number
305
- case 'Literal':
306
- /* c8 ignore next 2 -- `raw` may not be present in all parsers */
307
- return /** @type {string} */param.key.raw || param.key.value;
308
-
309
- // case 'MemberExpression':
310
- default:
311
- // Todo: We should really create a structure (and a corresponding
312
- // option analogous to `checkRestProperty`) which allows for
313
- // (and optionally requires) dynamic properties to have a single
314
- // line of documentation
315
- return undefined;
316
- }
317
- }
318
- if (param.type === 'ArrayPattern' || /** @type {import('estree').AssignmentPattern} */param.left?.type === 'ArrayPattern') {
319
- const elements = /** @type {import('estree').ArrayPattern} */param.elements || /** @type {import('estree').ArrayPattern} */(/** @type {import('estree').AssignmentPattern} */param.left)?.elements;
320
- const roots = elements.map((prop, idx) => {
321
- return {
322
- name: `"${idx}"`,
323
- restElement: prop?.type === 'RestElement'
324
- };
325
- });
326
- return [undefined, flattenRoots(roots)];
327
- }
328
- if (['ExperimentalRestProperty', 'RestElement'].includes(param.type)) {
329
- return {
330
- isRestProperty: isProperty,
331
- name: /** @type {import('@typescript-eslint/types').TSESTree.Identifier} */(/** @type {import('@typescript-eslint/types').TSESTree.RestElement} */param
332
- // @ts-expect-error Ok
333
- .argument).name ?? param?.argument?.elements?.map(({
334
- // @ts-expect-error Ok
335
- name
336
- }) => {
337
- return name;
338
- }),
339
- restElement: true
340
- };
341
- }
342
- if (param.type === 'TSParameterProperty') {
343
- return getParamName(/** @type {import('@typescript-eslint/types').TSESTree.Identifier} */
344
- /** @type {import('@typescript-eslint/types').TSESTree.TSParameterProperty} */param.parameter, true);
345
- }
346
- throw new Error(`Unsupported function signature format: \`${param.type}\`.`);
347
- };
348
- if (!functionNode) {
349
- return [];
350
- }
351
- return (/** @type {import('@typescript-eslint/types').TSESTree.TSFunctionType} */
352
- (/** @type {import('@typescript-eslint/types').TSESTree.TSPropertySignature} */functionNode?.typeAnnotation?.typeAnnotation)?.params || /** @type {import('@typescript-eslint/types').TSESTree.FunctionDeclaration} */functionNode.params || /** @type {import('@typescript-eslint/types').TSESTree.MethodDefinition} */functionNode.value?.params || []).map(param => {
353
- return getParamName(param);
354
- });
355
- };
356
-
357
- /**
358
- * @param {ESTreeOrTypeScriptNode} functionNode
359
- * @returns {Integer}
360
- */
361
- exports.getFunctionParameterNames = getFunctionParameterNames;
362
- const hasParams = functionNode => {
363
- // Should also check `functionNode.value.params` if supporting `MethodDefinition`
364
- return /** @type {import('@typescript-eslint/types').TSESTree.FunctionDeclaration} */functionNode.params.length;
365
- };
366
-
367
- /**
368
- * Gets all names of the target type, including those that refer to a path, e.g.
369
- * `foo` or `foo.bar`.
370
- * @param {import('comment-parser').Block} jsdoc
371
- * @param {string} targetTagName
372
- * @returns {{
373
- * idx: Integer,
374
- * name: string,
375
- * type: string
376
- * }[]}
377
- */
378
- exports.hasParams = hasParams;
379
- const getJsdocTagsDeep = (jsdoc, targetTagName) => {
380
- const ret = [];
381
- for (const [idx, {
382
- name,
383
- tag,
384
- type
385
- }] of jsdoc.tags.entries()) {
386
- if (tag !== targetTagName) {
387
- continue;
388
- }
389
- ret.push({
390
- idx,
391
- name,
392
- type
393
- });
394
- }
395
- return ret;
396
- };
397
- exports.getJsdocTagsDeep = getJsdocTagsDeep;
398
- const modeWarnSettings = (0, _WarnSettings.default)();
399
-
400
- /**
401
- * @param {ParserMode|undefined} mode
402
- * @param {import('eslint').Rule.RuleContext} context
403
- * @returns {import('./tagNames.js').AliasedTags}
404
- */
405
- const getTagNamesForMode = (mode, context) => {
406
- switch (mode) {
407
- case 'closure':
408
- case 'permissive':
409
- return _tagNames.closureTags;
410
- case 'jsdoc':
411
- return _tagNames.jsdocTags;
412
- case 'typescript':
413
- return _tagNames.typeScriptTags;
414
- default:
415
- if (!modeWarnSettings.hasBeenWarned(context, 'mode')) {
416
- context.report({
417
- loc: {
418
- end: {
419
- column: 1,
420
- line: 1
421
- },
422
- start: {
423
- column: 1,
424
- line: 1
425
- }
426
- },
427
- message: `Unrecognized value \`${mode}\` for \`settings.jsdoc.mode\`.`
428
- });
429
- modeWarnSettings.markSettingAsWarned(context, 'mode');
430
- }
431
-
432
- // We'll avoid breaking too many other rules
433
- return _tagNames.jsdocTags;
434
- }
435
- };
436
-
437
- /**
438
- * @param {import('comment-parser').Spec} tg
439
- * @param {boolean} [returnArray]
440
- * @returns {string[]|string}
441
- */
442
- const getTagDescription = (tg, returnArray) => {
443
- /**
444
- * @type {string[]}
445
- */
446
- const descriptions = [];
447
- tg.source.some(({
448
- tokens: {
449
- description,
450
- end,
451
- lineEnd,
452
- name,
453
- postDelimiter,
454
- postTag,
455
- tag,
456
- type
457
- }
458
- }) => {
459
- const desc = (tag && postTag || !tag && !name && !type && postDelimiter || ''
460
-
461
- // Remove space
462
- ).slice(1) + (description || '') + (lineEnd || '');
463
- if (end) {
464
- if (desc) {
465
- descriptions.push(desc);
466
- }
467
- return true;
468
- }
469
- descriptions.push(desc);
470
- return false;
471
- });
472
- return returnArray ? descriptions : descriptions.join('\n');
473
- };
474
-
475
- /**
476
- * @typedef {{
477
- * report: (descriptor: import('eslint').Rule.ReportDescriptor) => void
478
- * }} Reporter
479
- */
480
-
481
- /**
482
- * @param {string} name
483
- * @param {ParserMode|undefined} mode
484
- * @param {TagNamePreference} tagPreference
485
- * @param {import('eslint').Rule.RuleContext} context
486
- * @returns {string|false|{
487
- * message: string;
488
- * replacement?: string|undefined;
489
- * }}
490
- */
491
- exports.getTagDescription = getTagDescription;
492
- const getPreferredTagNameSimple = (name, mode, tagPreference = {},
493
- // @ts-expect-error Just a no-op
494
- // eslint-disable-next-line unicorn/no-object-as-default-parameter -- Ok
495
- context = {
496
- report() {
497
- // No-op
498
- }
499
- }) => {
500
- const prefValues = Object.values(tagPreference);
501
- if (prefValues.includes(name) || prefValues.some(prefVal => {
502
- return prefVal && typeof prefVal === 'object' && prefVal.replacement === name;
503
- })) {
504
- return name;
505
- }
506
-
507
- // Allow keys to have a 'tag ' prefix to avoid upstream bug in ESLint
508
- // that disallows keys that conflict with Object.prototype,
509
- // e.g. 'tag constructor' for 'constructor':
510
- // https://github.com/eslint/eslint/issues/13289
511
- // https://github.com/gajus/eslint-plugin-jsdoc/issues/537
512
- const tagPreferenceFixed = Object.fromEntries(Object.entries(tagPreference).map(([key, value]) => {
513
- return [key.replace(/^tag /v, ''), value];
514
- }));
515
- if (Object.hasOwn(tagPreferenceFixed, name)) {
516
- return tagPreferenceFixed[name];
517
- }
518
- const tagNames = getTagNamesForMode(mode, context);
519
- const preferredTagName = Object.entries(tagNames).find(([, aliases]) => {
520
- return aliases.includes(name);
521
- })?.[0];
522
- if (preferredTagName) {
523
- return preferredTagName;
524
- }
525
- return name;
526
- };
527
-
528
- /**
529
- * @param {import('eslint').Rule.RuleContext} context
530
- * @param {ParserMode|undefined} mode
531
- * @param {string} name
532
- * @param {string[]} definedTags
533
- * @returns {boolean}
534
- */
535
- exports.getPreferredTagNameSimple = getPreferredTagNameSimple;
536
- const isValidTag = (context, mode, name, definedTags) => {
537
- const tagNames = getTagNamesForMode(mode, context);
538
- const validTagNames = Object.keys(tagNames).concat(Object.values(tagNames).flat());
539
- const additionalTags = definedTags;
540
- const allTags = validTagNames.concat(additionalTags);
541
- return allTags.includes(name);
542
- };
543
-
544
- /**
545
- * @param {import('./iterateJsdoc.js').JsdocBlockWithInline} jsdoc
546
- * @param {string} targetTagName
547
- * @returns {boolean}
548
- */
549
- exports.isValidTag = isValidTag;
550
- const hasTag = (jsdoc, targetTagName) => {
551
- const targetTagLower = targetTagName.toLowerCase();
552
- return jsdoc.tags.some(doc => {
553
- return doc.tag.toLowerCase() === targetTagLower;
554
- });
555
- };
556
-
557
- /**
558
- * @param {import('./iterateJsdoc.js').JsdocBlockWithInline} jsdoc
559
- * @param {(tag: import('@es-joy/jsdoccomment').JsdocTagWithInline) => boolean} filter
560
- * @returns {import('@es-joy/jsdoccomment').JsdocTagWithInline[]}
561
- */
562
- exports.hasTag = hasTag;
563
- const filterTags = (jsdoc, filter) => {
564
- return jsdoc.tags.filter(tag => {
565
- return filter(tag);
566
- });
567
- };
568
-
569
- /**
570
- * @param {import('./iterateJsdoc.js').JsdocBlockWithInline} jsdoc
571
- * @param {string} tagName
572
- * @returns {import('comment-parser').Spec[]}
573
- */
574
- exports.filterTags = filterTags;
575
- const getTags = (jsdoc, tagName) => {
576
- return filterTags(jsdoc, item => {
577
- return item.tag === tagName;
578
- });
579
- };
580
-
581
- /**
582
- * @param {import('./iterateJsdoc.js').JsdocBlockWithInline} jsdoc
583
- * @param {{
584
- * tagName: string,
585
- * context?: import('eslint').Rule.RuleContext,
586
- * mode?: ParserMode,
587
- * report?: import('./iterateJsdoc.js').Report
588
- * tagNamePreference?: TagNamePreference
589
- * skipReportingBlockedTag?: boolean,
590
- * allowObjectReturn?: boolean,
591
- * defaultMessage?: string,
592
- * }} cfg
593
- * @returns {string|undefined|false|{
594
- * message: string;
595
- * replacement?: string|undefined;
596
- * }|{
597
- * blocked: true,
598
- * tagName: string
599
- * }}
600
- */
601
- exports.getTags = getTags;
602
- const getPreferredTagName = (jsdoc, {
603
- allowObjectReturn = false,
604
- context,
605
- tagName,
606
- defaultMessage = `Unexpected tag \`@${tagName}\``,
607
- mode,
608
- report = () => {},
609
- skipReportingBlockedTag = false,
610
- tagNamePreference
611
- }) => {
612
- const ret = getPreferredTagNameSimple(tagName, mode, tagNamePreference, context);
613
- const isObject = ret && typeof ret === 'object';
614
- if (hasTag(jsdoc, tagName) && (ret === false || isObject && !ret.replacement)) {
615
- if (skipReportingBlockedTag) {
616
- return {
617
- blocked: true,
618
- tagName
619
- };
620
- }
621
- const message = isObject && ret.message || defaultMessage;
622
- report(message, null, getTags(jsdoc, tagName)[0]);
623
- return false;
624
- }
625
- return isObject && !allowObjectReturn ? ret.replacement : ret;
626
- };
627
-
628
- /**
629
- * @param {import('./iterateJsdoc.js').JsdocBlockWithInline} jsdoc
630
- * @param {string} tagName
631
- * @param {(
632
- * matchingJsdocTag: import('@es-joy/jsdoccomment').JsdocTagWithInline,
633
- * targetTagName: string
634
- * ) => void} arrayHandler
635
- * @param {object} cfg
636
- * @param {import('eslint').Rule.RuleContext} [cfg.context]
637
- * @param {ParserMode} [cfg.mode]
638
- * @param {import('./iterateJsdoc.js').Report} [cfg.report]
639
- * @param {TagNamePreference} [cfg.tagNamePreference]
640
- * @param {boolean} [cfg.skipReportingBlockedTag]
641
- * @returns {void}
642
- */
643
- exports.getPreferredTagName = getPreferredTagName;
644
- const forEachPreferredTag = (jsdoc, tagName, arrayHandler, {
645
- context,
646
- mode,
647
- report,
648
- skipReportingBlockedTag = false,
649
- tagNamePreference
650
- } = {}) => {
651
- const targetTagName = /** @type {string|false} */
652
- getPreferredTagName(jsdoc, {
653
- context,
654
- mode,
655
- report,
656
- skipReportingBlockedTag,
657
- tagName,
658
- tagNamePreference
659
- });
660
- if (!targetTagName || skipReportingBlockedTag && targetTagName && typeof targetTagName === 'object') {
661
- return;
662
- }
663
- const matchingJsdocTags = jsdoc.tags.filter(({
664
- tag
665
- }) => {
666
- return tag === targetTagName;
667
- });
668
- for (const matchingJsdocTag of matchingJsdocTags) {
669
- arrayHandler(
670
- /**
671
- * @type {import('@es-joy/jsdoccomment').JsdocTagWithInline}
672
- */
673
- matchingJsdocTag, targetTagName);
674
- }
675
- };
676
-
677
- /**
678
- * Get all inline tags and inline tags in tags
679
- * @param {import('./iterateJsdoc.js').JsdocBlockWithInline} jsdoc
680
- * @returns {(import('comment-parser').Spec|
681
- * import('@es-joy/jsdoccomment').JsdocInlineTagNoType & {
682
- * line?: number | undefined; column?: number | undefined;
683
- * })[]}
684
- */
685
- exports.forEachPreferredTag = forEachPreferredTag;
686
- const getInlineTags = jsdoc => {
687
- return [...jsdoc.inlineTags.map(inlineTag => {
688
- // Tags don't have source or line numbers, so add before returning
689
- let line = -1;
690
- for (const {
691
- tokens: {
692
- description
693
- }
694
- } of jsdoc.source) {
695
- line++;
696
- if (description && description.includes(`{@${inlineTag.tag}`)) {
697
- break;
698
- }
699
- }
700
- inlineTag.line = line;
701
- return inlineTag;
702
- }), ...jsdoc.tags.flatMap(tag => {
703
- for (const inlineTag of tag.inlineTags) {
704
- /** @type {import('./iterateJsdoc.js').Integer} */
705
- let line = 0;
706
- for (const {
707
- number,
708
- tokens: {
709
- description
710
- }
711
- } of tag.source) {
712
- if (description && description.includes(`{@${inlineTag.tag}`)) {
713
- line = number;
714
- break;
715
- }
716
- }
717
- inlineTag.line = line;
718
- }
719
- return (
720
- /**
721
- * @type {import('comment-parser').Spec & {
722
- * inlineTags: import('@es-joy/jsdoccomment').JsdocInlineTagNoType[]
723
- * }}
724
- */
725
- tag.inlineTags
726
- );
727
- })];
728
- };
729
-
730
- /**
731
- * Get all tags, inline tags and inline tags in tags
732
- * @param {import('./iterateJsdoc.js').JsdocBlockWithInline} jsdoc
733
- * @returns {(import('comment-parser').Spec|
734
- * import('@es-joy/jsdoccomment').JsdocInlineTagNoType & {
735
- * line?: number | undefined; column?: number | undefined;
736
- * })[]}
737
- */
738
- exports.getInlineTags = getInlineTags;
739
- const getAllTags = jsdoc => {
740
- return [...jsdoc.tags, ...getInlineTags(jsdoc)];
741
- };
742
-
743
- /**
744
- * @param {import('./iterateJsdoc.js').JsdocBlockWithInline} jsdoc
745
- * @param {string[]} targetTagNames
746
- * @returns {boolean}
747
- */
748
- exports.getAllTags = getAllTags;
749
- const hasATag = (jsdoc, targetTagNames) => {
750
- return targetTagNames.some(targetTagName => {
751
- return hasTag(jsdoc, targetTagName);
752
- });
753
- };
754
-
755
- /**
756
- * Checks if the JSDoc comment has an undefined type.
757
- * @param {import('comment-parser').Spec|null|undefined} tag
758
- * the tag which should be checked.
759
- * @param {ParserMode} mode
760
- * @returns {boolean}
761
- * true in case a defined type is undeclared; otherwise false.
762
- */
763
- exports.hasATag = hasATag;
764
- const mayBeUndefinedTypeTag = (tag, mode) => {
765
- // The function should not continue in the event the type is not defined...
766
- if (typeof tag === 'undefined' || tag === null) {
767
- return true;
768
- }
769
-
770
- // .. same applies if it declares an `{undefined}` or `{void}` type
771
- const tagType = tag.type.trim();
772
-
773
- // Exit early if matching
774
- if (tagType === 'undefined' || tagType === 'void' || tagType === '*' || tagType === 'any') {
775
- return true;
776
- }
777
- let parsedTypes;
778
- try {
779
- parsedTypes = (0, _jsdoccomment.tryParse)(tagType, mode === 'permissive' ? undefined : [mode]);
780
- } catch {
781
- // Ignore
782
- }
783
- if (
784
- // We do not traverse deeply as it could be, e.g., `Promise<void>`
785
- parsedTypes && parsedTypes.type === 'JsdocTypeUnion' && parsedTypes.elements.some(elem => {
786
- return elem.type === 'JsdocTypeUndefined' || elem.type === 'JsdocTypeName' && elem.value === 'void';
787
- })) {
788
- return true;
789
- }
790
-
791
- // In any other case, a type is present
792
- return false;
793
- };
794
-
795
- /**
796
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} map
797
- * @param {string} tag
798
- * @returns {Map<string, string|string[]|boolean|undefined>}
799
- */
800
- exports.mayBeUndefinedTypeTag = mayBeUndefinedTypeTag;
801
- const ensureMap = (map, tag) => {
802
- if (!map.has(tag)) {
803
- map.set(tag, new Map());
804
- }
805
- return /** @type {Map<string, string | boolean>} */map.get(tag);
806
- };
807
-
808
- /**
809
- * @param {import('./iterateJsdoc.js').StructuredTags} structuredTags
810
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
811
- * @returns {void}
812
- */
813
- const overrideTagStructure = (structuredTags, tagMap = tagStructure) => {
814
- for (const [tag, {
815
- name,
816
- required = [],
817
- type
818
- }] of Object.entries(structuredTags)) {
819
- const tagStruct = ensureMap(tagMap, tag);
820
- tagStruct.set('namepathRole', name);
821
- tagStruct.set('typeAllowed', type);
822
- const requiredName = required.includes('name');
823
- if (requiredName && name === false) {
824
- throw new Error('Cannot add "name" to `require` with the tag\'s `name` set to `false`');
825
- }
826
- tagStruct.set('nameRequired', requiredName);
827
- const requiredType = required.includes('type');
828
- if (requiredType && type === false) {
829
- throw new Error('Cannot add "type" to `require` with the tag\'s `type` set to `false`');
830
- }
831
- tagStruct.set('typeRequired', requiredType);
832
- const typeOrNameRequired = required.includes('typeOrNameRequired');
833
- if (typeOrNameRequired && name === false) {
834
- throw new Error('Cannot add "typeOrNameRequired" to `require` with the tag\'s `name` set to `false`');
835
- }
836
- if (typeOrNameRequired && type === false) {
837
- throw new Error('Cannot add "typeOrNameRequired" to `require` with the tag\'s `type` set to `false`');
838
- }
839
- tagStruct.set('typeOrNameRequired', typeOrNameRequired);
840
- }
841
- };
842
-
843
- /**
844
- * @param {ParserMode} mode
845
- * @param {import('./iterateJsdoc.js').StructuredTags} structuredTags
846
- * @returns {import('./getDefaultTagStructureForMode.js').TagStructure}
847
- */
848
- exports.overrideTagStructure = overrideTagStructure;
849
- const getTagStructureForMode = (mode, structuredTags) => {
850
- const tagStruct = (0, _getDefaultTagStructureForMode.default)(mode);
851
- try {
852
- overrideTagStructure(structuredTags, tagStruct);
853
- /* c8 ignore next 3 */
854
- } catch {
855
- //
856
- }
857
- return tagStruct;
858
- };
859
-
860
- /**
861
- * @param {string} tag
862
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
863
- * @returns {boolean}
864
- */
865
- exports.getTagStructureForMode = getTagStructureForMode;
866
- const isNameOrNamepathDefiningTag = (tag, tagMap = tagStructure) => {
867
- const tagStruct = ensureMap(tagMap, tag);
868
- return /** @type {(string|boolean|undefined)[]} */['name-defining', 'namepath-defining'].includes(/** @type {string|boolean|undefined} */
869
- tagStruct.get('namepathRole'));
870
- };
871
-
872
- /**
873
- * @param {import('eslint').SourceCode} sourceCode
874
- * @returns {import('@es-joy/jsdoccomment').JsdocBlockWithInline[]}
875
- */
876
- exports.isNameOrNamepathDefiningTag = isNameOrNamepathDefiningTag;
877
- const getJSDocCommentBlocks = sourceCode => {
878
- return sourceCode.getAllComments().filter(comment => {
879
- return /^\*(?!\*)/v.test(comment.value);
880
- }).map(commentNode => {
881
- return (0, _jsdoccomment.parseComment)(commentNode, '');
882
- });
883
- };
884
-
885
- /**
886
- * @param {import('eslint').SourceCode} sourceCode
887
- * @returns {import('comment-parser').Spec[]}
888
- */
889
- exports.getJSDocCommentBlocks = getJSDocCommentBlocks;
890
- const getDocumentNamepathDefiningTags = sourceCode => {
891
- return getJSDocCommentBlocks(sourceCode).flatMap(doc => {
892
- return doc.tags.filter(({
893
- tag
894
- }) => {
895
- return isNameOrNamepathDefiningTag(tag) && !['arg', 'argument', 'param', 'prop', 'property'].includes(tag);
896
- });
897
- });
898
- };
899
-
900
- /**
901
- * @param {string} tag
902
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
903
- * @returns {boolean}
904
- */
905
- exports.getDocumentNamepathDefiningTags = getDocumentNamepathDefiningTags;
906
- const isNamepathReferencingTag = (tag, tagMap = tagStructure) => {
907
- const tagStruct = ensureMap(tagMap, tag);
908
- return tagStruct.get('namepathRole') === 'namepath-referencing';
909
- };
910
-
911
- /**
912
- * @param {string} tag
913
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
914
- * @returns {boolean}
915
- */
916
- exports.isNamepathReferencingTag = isNamepathReferencingTag;
917
- const isNamepathOrUrlReferencingTag = (tag, tagMap = tagStructure) => {
918
- const tagStruct = ensureMap(tagMap, tag);
919
- return tagStruct.get('namepathRole') === 'namepath-or-url-referencing';
920
- };
921
-
922
- /**
923
- * @param {string} tag
924
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
925
- * @returns {boolean|undefined}
926
- */
927
- exports.isNamepathOrUrlReferencingTag = isNamepathOrUrlReferencingTag;
928
- const tagMustHaveTypePosition = (tag, tagMap = tagStructure) => {
929
- const tagStruct = ensureMap(tagMap, tag);
930
- return /** @type {boolean|undefined} */tagStruct.get('typeRequired');
931
- };
932
-
933
- /**
934
- * @param {string} tag
935
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
936
- * @returns {boolean|string}
937
- */
938
- exports.tagMustHaveTypePosition = tagMustHaveTypePosition;
939
- const tagMightHaveTypePosition = (tag, tagMap = tagStructure) => {
940
- if (tagMustHaveTypePosition(tag, tagMap)) {
941
- return true;
942
- }
943
- const tagStruct = ensureMap(tagMap, tag);
944
- const ret = /** @type {boolean|undefined} */tagStruct.get('typeAllowed');
945
- return ret === undefined ? true : ret;
946
- };
947
- exports.tagMightHaveTypePosition = tagMightHaveTypePosition;
948
- const namepathTypes = new Set(['name-defining', 'namepath-defining', 'namepath-referencing']);
949
-
950
- /**
951
- * @param {string} tag
952
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
953
- * @returns {boolean}
954
- */
955
- const tagMightHaveNamePosition = (tag, tagMap = tagStructure) => {
956
- const tagStruct = ensureMap(tagMap, tag);
957
- const ret = tagStruct.get('namepathRole');
958
- return ret === undefined ? true : Boolean(ret);
959
- };
960
-
961
- /**
962
- * @param {string} tag
963
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
964
- * @returns {boolean}
965
- */
966
- exports.tagMightHaveNamePosition = tagMightHaveNamePosition;
967
- const tagMightHaveNameOrNamepath = (tag, tagMap = tagStructure) => {
968
- const tagStruct = ensureMap(tagMap, tag);
969
- const nampathRole = tagStruct.get('namepathRole');
970
- return nampathRole !== false && namepathTypes.has(/** @type {string} */nampathRole);
971
- };
972
-
973
- /**
974
- * @param {string} tag
975
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
976
- * @returns {boolean}
977
- */
978
- exports.tagMightHaveNameOrNamepath = tagMightHaveNameOrNamepath;
979
- const tagMightHaveNamepath = (tag, tagMap = tagStructure) => {
980
- const tagStruct = ensureMap(tagMap, tag);
981
- const nampathRole = tagStruct.get('namepathRole');
982
- return nampathRole !== false && ['namepath-defining', 'namepath-referencing'].includes(/** @type {string} */nampathRole);
983
- };
984
-
985
- /**
986
- * @param {string} tag
987
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
988
- * @returns {boolean}
989
- */
990
- exports.tagMightHaveNamepath = tagMightHaveNamepath;
991
- const tagMightHaveName = (tag, tagMap = tagStructure) => {
992
- const tagStruct = ensureMap(tagMap, tag);
993
- const nampathRole = tagStruct.get('namepathRole');
994
- return nampathRole !== false && nampathRole === 'name-defining';
995
- };
996
-
997
- /**
998
- * @param {string} tag
999
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
1000
- * @returns {boolean|undefined}
1001
- */
1002
- exports.tagMightHaveName = tagMightHaveName;
1003
- const tagMustHaveNamePosition = (tag, tagMap = tagStructure) => {
1004
- const tagStruct = ensureMap(tagMap, tag);
1005
- return /** @type {boolean|undefined} */tagStruct.get('nameRequired');
1006
- };
1007
-
1008
- /**
1009
- * @param {string} tag
1010
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
1011
- * @returns {boolean}
1012
- */
1013
- exports.tagMustHaveNamePosition = tagMustHaveNamePosition;
1014
- const tagMightHaveEitherTypeOrNamePosition = (tag, tagMap) => {
1015
- return Boolean(tagMightHaveTypePosition(tag, tagMap)) || tagMightHaveNameOrNamepath(tag, tagMap);
1016
- };
1017
-
1018
- /**
1019
- * @param {string} tag
1020
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
1021
- * @returns {boolean|undefined}
1022
- */
1023
- exports.tagMightHaveEitherTypeOrNamePosition = tagMightHaveEitherTypeOrNamePosition;
1024
- const tagMustHaveEitherTypeOrNamePosition = (tag, tagMap) => {
1025
- const tagStruct = ensureMap(tagMap, tag);
1026
- return /** @type {boolean} */tagStruct.get('typeOrNameRequired');
1027
- };
1028
-
1029
- /**
1030
- * @param {import('comment-parser').Spec} tag
1031
- * @param {import('./getDefaultTagStructureForMode.js').TagStructure} tagMap
1032
- * @returns {boolean|undefined}
1033
- */
1034
- const tagMissingRequiredTypeOrNamepath = (tag, tagMap = tagStructure) => {
1035
- const mustHaveTypePosition = tagMustHaveTypePosition(tag.tag, tagMap);
1036
- const mightHaveTypePosition = tagMightHaveTypePosition(tag.tag, tagMap);
1037
- const hasTypePosition = mightHaveTypePosition && Boolean(tag.type);
1038
- const hasNameOrNamepathPosition = (tagMustHaveNamePosition(tag.tag, tagMap) || tagMightHaveNameOrNamepath(tag.tag, tagMap)) && Boolean(tag.name);
1039
- const mustHaveEither = tagMustHaveEitherTypeOrNamePosition(tag.tag, tagMap);
1040
- const hasEither = tagMightHaveEitherTypeOrNamePosition(tag.tag, tagMap) && (hasTypePosition || hasNameOrNamepathPosition);
1041
- return mustHaveEither && !hasEither && !mustHaveTypePosition;
1042
- };
1043
-
1044
- /* eslint-disable complexity -- Temporary */
1045
- /**
1046
- * @param {ESTreeOrTypeScriptNode|null|undefined} node
1047
- * @param {boolean} [checkYieldReturnValue]
1048
- * @returns {boolean}
1049
- */
1050
- exports.tagMissingRequiredTypeOrNamepath = tagMissingRequiredTypeOrNamepath;
1051
- const hasNonFunctionYield = (node, checkYieldReturnValue) => {
1052
- /* eslint-enable complexity -- Temporary */
1053
- if (!node) {
1054
- return false;
1055
- }
1056
- switch (node.type) {
1057
- case 'ArrayExpression':
1058
- case 'ArrayPattern':
1059
- return node.elements.some(element => {
1060
- return hasNonFunctionYield(element, checkYieldReturnValue);
1061
- });
1062
- case 'AssignmentExpression':
1063
- case 'BinaryExpression':
1064
- case 'LogicalExpression':
1065
- {
1066
- return hasNonFunctionYield(node.left, checkYieldReturnValue) || hasNonFunctionYield(node.right, checkYieldReturnValue);
1067
- }
1068
- case 'AssignmentPattern':
1069
- return hasNonFunctionYield(node.right, checkYieldReturnValue);
1070
- case 'BlockStatement':
1071
- {
1072
- return node.body.some(bodyNode => {
1073
- return !['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression'].includes(bodyNode.type) && hasNonFunctionYield(bodyNode, checkYieldReturnValue);
1074
- });
1075
- }
1076
-
1077
- /* c8 ignore next 2 -- In Babel? */
1078
- case 'CallExpression':
1079
- // @ts-expect-error In Babel?
1080
- case 'OptionalCallExpression':
1081
- return node.arguments.some(element => {
1082
- return hasNonFunctionYield(element, checkYieldReturnValue);
1083
- });
1084
- case 'ChainExpression':
1085
- case 'ExpressionStatement':
1086
- {
1087
- return hasNonFunctionYield(node.expression, checkYieldReturnValue);
1088
- }
1089
-
1090
- /* c8 ignore next 2 -- In Babel? */
1091
- // @ts-expect-error In Babel?
1092
- case 'ClassProperty':
1093
-
1094
- /* c8 ignore next 2 -- In Babel? */
1095
- // @ts-expect-error In Babel?
1096
- case 'ObjectProperty':
1097
- /* c8 ignore next 2 -- In Babel? */
1098
- case 'Property':
1099
- case 'PropertyDefinition':
1100
- return node.computed && hasNonFunctionYield(node.key, checkYieldReturnValue) || hasNonFunctionYield(node.value, checkYieldReturnValue);
1101
- case 'ConditionalExpression':
1102
- case 'IfStatement':
1103
- {
1104
- return hasNonFunctionYield(node.test, checkYieldReturnValue) || hasNonFunctionYield(node.consequent, checkYieldReturnValue) || hasNonFunctionYield(node.alternate, checkYieldReturnValue);
1105
- }
1106
- case 'DoWhileStatement':
1107
- case 'ForInStatement':
1108
- case 'ForOfStatement':
1109
- case 'ForStatement':
1110
- case 'LabeledStatement':
1111
- case 'WhileStatement':
1112
- case 'WithStatement':
1113
- {
1114
- return hasNonFunctionYield(node.body, checkYieldReturnValue);
1115
- }
1116
-
1117
- /* c8 ignore next 2 -- In Babel? */
1118
- // @ts-expect-error In Babel?
1119
- case 'Import':
1120
- case 'ImportExpression':
1121
- return hasNonFunctionYield(node.source, checkYieldReturnValue);
1122
-
1123
- // ?.
1124
- /* c8 ignore next 2 -- In Babel? */
1125
- case 'MemberExpression':
1126
- // @ts-expect-error In Babel?
1127
- case 'OptionalMemberExpression':
1128
- return hasNonFunctionYield(node.object, checkYieldReturnValue) || hasNonFunctionYield(node.property, checkYieldReturnValue);
1129
- case 'ObjectExpression':
1130
- case 'ObjectPattern':
1131
- return node.properties.some(property => {
1132
- return hasNonFunctionYield(property, checkYieldReturnValue);
1133
- });
1134
- /* c8 ignore next 2 -- In Babel? */
1135
- // @ts-expect-error In Babel?
1136
- case 'ObjectMethod':
1137
- /* c8 ignore next 6 -- In Babel? */
1138
- // @ts-expect-error In Babel?
1139
- return node.computed && hasNonFunctionYield(node.key, checkYieldReturnValue) ||
1140
- // @ts-expect-error In Babel?
1141
- node.arguments.some(nde => {
1142
- return hasNonFunctionYield(nde, checkYieldReturnValue);
1143
- });
1144
- case 'ReturnStatement':
1145
- {
1146
- if (node.argument === null) {
1147
- return false;
1148
- }
1149
- return hasNonFunctionYield(node.argument, checkYieldReturnValue);
1150
- }
1151
-
1152
- // Comma
1153
- case 'SequenceExpression':
1154
- case 'TemplateLiteral':
1155
- return node.expressions.some(subExpression => {
1156
- return hasNonFunctionYield(subExpression, checkYieldReturnValue);
1157
- });
1158
- case 'SpreadElement':
1159
- case 'UnaryExpression':
1160
- return hasNonFunctionYield(node.argument, checkYieldReturnValue);
1161
- case 'SwitchStatement':
1162
- {
1163
- return node.cases.some(someCase => {
1164
- return someCase.consequent.some(nde => {
1165
- return hasNonFunctionYield(nde, checkYieldReturnValue);
1166
- });
1167
- });
1168
- }
1169
- case 'TaggedTemplateExpression':
1170
- return hasNonFunctionYield(node.quasi, checkYieldReturnValue);
1171
- case 'TryStatement':
1172
- {
1173
- return hasNonFunctionYield(node.block, checkYieldReturnValue) || hasNonFunctionYield(node.handler && node.handler.body, checkYieldReturnValue) || hasNonFunctionYield(/** @type {import('@typescript-eslint/types').TSESTree.BlockStatement} */
1174
- node.finalizer, checkYieldReturnValue);
1175
- }
1176
- case 'VariableDeclaration':
1177
- {
1178
- return node.declarations.some(nde => {
1179
- return hasNonFunctionYield(nde, checkYieldReturnValue);
1180
- });
1181
- }
1182
- case 'VariableDeclarator':
1183
- {
1184
- return hasNonFunctionYield(node.id, checkYieldReturnValue) || hasNonFunctionYield(node.init, checkYieldReturnValue);
1185
- }
1186
- case 'YieldExpression':
1187
- {
1188
- if (checkYieldReturnValue) {
1189
- if (/** @type {import('eslint').Rule.Node} */node.parent?.type === 'VariableDeclarator') {
1190
- return true;
1191
- }
1192
- return false;
1193
- }
1194
-
1195
- // void return does not count.
1196
- if (node.argument === null) {
1197
- return false;
1198
- }
1199
- return true;
1200
- }
1201
- default:
1202
- {
1203
- return false;
1204
- }
1205
- }
1206
- };
1207
-
1208
- /**
1209
- * Checks if a node has a return statement. Void return does not count.
1210
- * @param {ESTreeOrTypeScriptNode} node
1211
- * @param {boolean} [checkYieldReturnValue]
1212
- * @returns {boolean}
1213
- */
1214
- const hasYieldValue = (node, checkYieldReturnValue) => {
1215
- return /** @type {import('@typescript-eslint/types').TSESTree.FunctionDeclaration} */node.generator && (/** @type {import('@typescript-eslint/types').TSESTree.FunctionDeclaration} */node.expression || hasNonFunctionYield(/** @type {import('@typescript-eslint/types').TSESTree.FunctionDeclaration} */
1216
- node.body, checkYieldReturnValue));
1217
- };
1218
-
1219
- /**
1220
- * Checks if a node has a throws statement.
1221
- * @param {ESTreeOrTypeScriptNode|null|undefined} node
1222
- * @param {boolean} [innerFunction]
1223
- * @returns {boolean}
1224
- */
1225
- exports.hasYieldValue = hasYieldValue;
1226
- const hasThrowValue = (node, innerFunction) => {
1227
- if (!node) {
1228
- return false;
1229
- }
1230
-
1231
- // There are cases where a function may execute its inner function which
1232
- // throws, but we're treating functions atomically rather than trying to
1233
- // follow them
1234
- switch (node.type) {
1235
- case 'ArrowFunctionExpression':
1236
- case 'FunctionDeclaration':
1237
- case 'FunctionExpression':
1238
- {
1239
- return !innerFunction && !node.async && hasThrowValue(node.body, true);
1240
- }
1241
- case 'BlockStatement':
1242
- {
1243
- return node.body.some(bodyNode => {
1244
- return bodyNode.type !== 'FunctionDeclaration' && hasThrowValue(bodyNode);
1245
- });
1246
- }
1247
- case 'DoWhileStatement':
1248
- case 'ForInStatement':
1249
- case 'ForOfStatement':
1250
- case 'ForStatement':
1251
- case 'LabeledStatement':
1252
- case 'WhileStatement':
1253
- case 'WithStatement':
1254
- {
1255
- return hasThrowValue(node.body);
1256
- }
1257
- case 'IfStatement':
1258
- {
1259
- return hasThrowValue(node.consequent) || hasThrowValue(node.alternate);
1260
- }
1261
- case 'SwitchStatement':
1262
- {
1263
- return node.cases.some(someCase => {
1264
- return someCase.consequent.some(nde => {
1265
- return hasThrowValue(nde);
1266
- });
1267
- });
1268
- }
1269
- case 'ThrowStatement':
1270
- {
1271
- return true;
1272
- }
1273
-
1274
- // We only consider it to throw an error if the catch or finally blocks throw an error.
1275
- case 'TryStatement':
1276
- {
1277
- return hasThrowValue(node.handler && node.handler.body) || hasThrowValue(node.finalizer);
1278
- }
1279
- default:
1280
- {
1281
- return false;
1282
- }
1283
- }
1284
- };
1285
-
1286
- /**
1287
- * @param {string} tag
1288
- */
1289
- /*
1290
- const isInlineTag = (tag) => {
1291
- return /^(@link|@linkcode|@linkplain|@tutorial) /v.test(tag);
1292
- };
1293
- */
1294
-
1295
- /**
1296
- * Splits a `@template` tag's names on commas that separate template entries,
1297
- * ignoring commas nested within a type expression so that default values such
1298
- * as `[T=Record<string, unknown>]` are not split apart.
1299
- *
1300
- * Only `<`, `(` and `{` are treated as nesting: a comma within them is part of
1301
- * a type (generic arguments, function params, object type). Square brackets are
1302
- * deliberately not counted, since `[...]` is the optional/default wrapper in
1303
- * which commas do separate entries, e.g. `[T=string, U=number]`.
1304
- * @param {string} str
1305
- * @returns {string[]}
1306
- */
1307
- exports.hasThrowValue = hasThrowValue;
1308
- const splitTopLevelCommas = str => {
1309
- const parts = [];
1310
- let depth = 0;
1311
- let current = '';
1312
- for (const char of str) {
1313
- if (char === '<' || char === '{' || char === '(') {
1314
- depth++;
1315
- } else if (char === '>' || char === '}' || char === ')') {
1316
- depth = Math.max(0, depth - 1);
1317
- }
1318
- if (char === ',' && depth === 0) {
1319
- parts.push(current);
1320
- current = '';
1321
- } else {
1322
- current += char;
1323
- }
1324
- }
1325
- parts.push(current);
1326
- return parts;
1327
- };
1328
-
1329
- /**
1330
- * Parses GCC Generic/Template types
1331
- * @see {@link https://github.com/google/closure-compiler/wiki/Generic-Types}
1332
- * @see {@link https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#template}
1333
- * @param {import('comment-parser').Spec} tag
1334
- * @returns {string[]}
1335
- */
1336
- const parseClosureTemplateTag = tag => {
1337
- return splitTopLevelCommas(tag.name).map(type => {
1338
- return type.trim().replace(/^\[?(?<name>.*?)=.*$/v, '$<name>');
1339
- });
1340
- };
1341
-
1342
- /**
1343
- * @typedef {true|string[]} DefaultContexts
1344
- */
1345
-
1346
- /**
1347
- * Checks user option for `contexts` array, defaulting to
1348
- * contexts designated by the rule. Returns an array of
1349
- * ESTree AST types, indicating allowable contexts.
1350
- * @param {import('eslint').Rule.RuleContext} context
1351
- * @param {DefaultContexts|undefined} defaultContexts
1352
- * @param {{
1353
- * contexts?: import('./iterateJsdoc.js').Context[]
1354
- * }} settings
1355
- * @returns {(string|import('./iterateJsdoc.js').ContextObject)[]}
1356
- */
1357
- exports.parseClosureTemplateTag = parseClosureTemplateTag;
1358
- const enforcedContexts = (context, defaultContexts, settings) => {
1359
- const contexts = context.options[0]?.contexts || settings.contexts || (defaultContexts === true ? ['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'TSDeclareFunction'] : defaultContexts);
1360
- return contexts;
1361
- };
1362
-
1363
- /**
1364
- * @param {import('./iterateJsdoc.js').Context[]} contexts
1365
- * @param {import('./iterateJsdoc.js').CheckJsdoc} checkJsdoc
1366
- * @param {import('@es-joy/jsdoccomment').CommentHandler} [handler]
1367
- * @returns {import('eslint').Rule.RuleListener}
1368
- */
1369
- exports.enforcedContexts = enforcedContexts;
1370
- const getContextObject = (contexts, checkJsdoc, handler) => {
1371
- /** @type {import('eslint').Rule.RuleListener} */
1372
- const properties = {};
1373
- for (const [idx, prop] of contexts.entries()) {
1374
- /** @type {string} */
1375
- let property;
1376
-
1377
- /** @type {(node: import('eslint').Rule.Node) => void} */
1378
- let value;
1379
- if (typeof prop === 'object') {
1380
- const selInfo = {
1381
- lastIndex: idx,
1382
- selector: prop.context
1383
- };
1384
- if (prop.comment) {
1385
- property = /** @type {string} */prop.context;
1386
- value = checkJsdoc.bind(null, {
1387
- ...selInfo,
1388
- comment: prop.comment
1389
- },
1390
- /**
1391
- * @type {(jsdoc: import('@es-joy/jsdoccomment').JsdocBlockWithInline) => boolean}
1392
- */
1393
- /** @type {import('@es-joy/jsdoccomment').CommentHandler} */
1394
- handler.bind(null, prop.comment));
1395
- } else {
1396
- property = /** @type {string} */prop.context;
1397
- value = checkJsdoc.bind(null, selInfo, null);
1398
- }
1399
- } else {
1400
- const selInfo = {
1401
- lastIndex: idx,
1402
- selector: prop
1403
- };
1404
- property = prop;
1405
- value = checkJsdoc.bind(null, selInfo, null);
1406
- }
1407
- const old =
1408
- /**
1409
- * @type {((node: import('eslint').Rule.Node) => void)}
1410
- */
1411
- properties[property];
1412
- properties[property] = old ?
1413
- /**
1414
- * @type {((node: import('eslint').Rule.Node) => void)}
1415
- */
1416
- function (node) {
1417
- old(node);
1418
- value(node);
1419
- } : value;
1420
- }
1421
- return properties;
1422
- };
1423
- exports.getContextObject = getContextObject;
1424
- const tagsWithNamesAndDescriptions = new Set(['arg', 'argument', 'param', 'prop', 'property', 'return',
1425
- // These two are parsed by our custom parser as though having a `name`
1426
- 'returns', 'template']);
1427
-
1428
- /**
1429
- * @typedef {{
1430
- * [key: string]: false|string|
1431
- * {message: string, replacement?: string}
1432
- * }} TagNamePreference
1433
- */
1434
-
1435
- /**
1436
- * @param {import('eslint').Rule.RuleContext} context
1437
- * @param {ParserMode|undefined} mode
1438
- * @param {import('comment-parser').Spec[]} tags
1439
- * @returns {{
1440
- * tagsWithNames: import('comment-parser').Spec[],
1441
- * tagsWithoutNames: import('comment-parser').Spec[]
1442
- * }}
1443
- */
1444
- const getTagsByType = (context, mode, tags) => {
1445
- /**
1446
- * @type {import('comment-parser').Spec[]}
1447
- */
1448
- const tagsWithoutNames = [];
1449
- const tagsWithNames = tags.filter(tag => {
1450
- const {
1451
- tag: tagName
1452
- } = tag;
1453
- const tagWithName = tagsWithNamesAndDescriptions.has(tagName);
1454
- if (!tagWithName) {
1455
- tagsWithoutNames.push(tag);
1456
- }
1457
- return tagWithName;
1458
- });
1459
- return {
1460
- tagsWithNames,
1461
- tagsWithoutNames
1462
- };
1463
- };
1464
-
1465
- /**
1466
- * @param {import('eslint').SourceCode|{
1467
- * text: string
1468
- * }} sourceCode
1469
- * @returns {string}
1470
- */
1471
- exports.getTagsByType = getTagsByType;
1472
- const getIndent = sourceCode => {
1473
- return (sourceCode.text.match(/^\n*([ \t]+)/v)?.[1] ?? '') + ' ';
1474
- };
1475
-
1476
- /**
1477
- * @param {import('eslint').Rule.Node|null} node
1478
- * @returns {boolean}
1479
- */
1480
- exports.getIndent = getIndent;
1481
- const isConstructor = node => {
1482
- return node?.type === 'MethodDefinition' && node.kind === 'constructor' || /** @type {import('@typescript-eslint/types').TSESTree.MethodDefinition} */node?.parent?.kind === 'constructor';
1483
- };
1484
-
1485
- /**
1486
- * @param {import('eslint').Rule.Node|null} node
1487
- * @returns {boolean}
1488
- */
1489
- exports.isConstructor = isConstructor;
1490
- const isGetter = node => {
1491
- return node !== null &&
1492
- /**
1493
- * @type {import('@typescript-eslint/types').TSESTree.MethodDefinition|
1494
- * import('@typescript-eslint/types').TSESTree.Property}
1495
- */
1496
- node.parent?.kind === 'get';
1497
- };
1498
-
1499
- /**
1500
- * @param {import('eslint').Rule.Node|null} node
1501
- * @returns {boolean}
1502
- */
1503
- exports.isGetter = isGetter;
1504
- const isSetter = node => {
1505
- return node !== null &&
1506
- /**
1507
- * @type {import('@typescript-eslint/types').TSESTree.MethodDefinition|
1508
- * import('@typescript-eslint/types').TSESTree.Property}
1509
- */
1510
- node.parent?.kind === 'set';
1511
- };
1512
-
1513
- /**
1514
- * @param {import('eslint').Rule.Node} node
1515
- * @returns {boolean}
1516
- */
1517
- exports.isSetter = isSetter;
1518
- const hasAccessorPair = node => {
1519
- const {
1520
- key,
1521
- kind: sourceKind,
1522
- type
1523
- } =
1524
- /**
1525
- * @type {import('@typescript-eslint/types').TSESTree.MethodDefinition|
1526
- * import('@typescript-eslint/types').TSESTree.Property}
1527
- */
1528
- node;
1529
- const sourceName = /** @type {import('@typescript-eslint/types').TSESTree.Identifier} */key.name;
1530
- const oppositeKind = sourceKind === 'get' ? 'set' : 'get';
1531
- const sibling = type === 'MethodDefinition' ? /** @type {import('@typescript-eslint/types').TSESTree.ClassBody} */node.parent.body : /** @type {import('@typescript-eslint/types').TSESTree.ObjectExpression} */node.parent.properties;
1532
- return sibling.some(child => {
1533
- const {
1534
- key: ky,
1535
- kind
1536
- } =
1537
- /**
1538
- * @type {import('@typescript-eslint/types').TSESTree.MethodDefinition|
1539
- * import('@typescript-eslint/types').TSESTree.Property}
1540
- */
1541
- child;
1542
- const name = /** @type {import('@typescript-eslint/types').TSESTree.Identifier} */ky.name;
1543
- return kind === oppositeKind && name === sourceName;
1544
- });
1545
- };
1546
-
1547
- /**
1548
- * @param {import('./iterateJsdoc.js').JsdocBlockWithInline} jsdoc
1549
- * @param {import('eslint').Rule.Node|null} node
1550
- * @param {import('eslint').Rule.RuleContext} context
1551
- * @param {import('json-schema').JSONSchema4} schema
1552
- * @returns {boolean}
1553
- */
1554
- const exemptSpeciaMethods = (jsdoc, node, context, schema) => {
1555
- /**
1556
- * @param {"checkGetters"|"checkSetters"|"checkConstructors"} prop
1557
- * @returns {boolean|"no-setter"|"no-getter"}
1558
- */
1559
- const hasSchemaOption = prop => {
1560
- const schemaProperties = schema[0].properties;
1561
- return context.options[0]?.[prop] ?? (schemaProperties[prop] && schemaProperties[prop].default);
1562
- };
1563
- const checkGetters = hasSchemaOption('checkGetters');
1564
- const checkSetters = hasSchemaOption('checkSetters');
1565
- return !hasSchemaOption('checkConstructors') && (isConstructor(node) || hasATag(jsdoc, ['class', 'constructor'])) || isGetter(node) && (!checkGetters || checkGetters === 'no-setter' && hasAccessorPair(/** @type {import('./iterateJsdoc.js').Node} */
1566
- /** @type {import('./iterateJsdoc.js').Node} */node.parent)) || isSetter(node) && (!checkSetters || checkSetters === 'no-getter' && hasAccessorPair(/** @type {import('./iterateJsdoc.js').Node} */
1567
- /** @type {import('./iterateJsdoc.js').Node} */node.parent));
1568
- };
1569
-
1570
- /**
1571
- * Since path segments may be unquoted (if matching a reserved word,
1572
- * identifier or numeric literal) or single or double quoted, in either
1573
- * the `@param` or in source, we need to strip the quotes to give a fair
1574
- * comparison.
1575
- * @param {string} str
1576
- * @returns {string}
1577
- */
1578
- exports.exemptSpeciaMethods = exemptSpeciaMethods;
1579
- const dropPathSegmentQuotes = str => {
1580
- return str.replaceAll(/\.(['"])(.*)\1/gv, '.$2');
1581
- };
1582
-
1583
- /**
1584
- * @param {string} name
1585
- * @returns {(otherPathName: string) => boolean}
1586
- */
1587
- exports.dropPathSegmentQuotes = dropPathSegmentQuotes;
1588
- const comparePaths = name => {
1589
- return otherPathName => {
1590
- return otherPathName === name || dropPathSegmentQuotes(otherPathName) === dropPathSegmentQuotes(name);
1591
- };
1592
- };
1593
-
1594
- /**
1595
- * @callback PathDoesNotBeginWith
1596
- * @param {string} name
1597
- * @param {string} otherPathName
1598
- * @returns {boolean}
1599
- */
1600
-
1601
- /** @type {PathDoesNotBeginWith} */
1602
- exports.comparePaths = comparePaths;
1603
- const pathDoesNotBeginWith = (name, otherPathName) => {
1604
- return !name.startsWith(otherPathName) && !dropPathSegmentQuotes(name).startsWith(dropPathSegmentQuotes(otherPathName));
1605
- };
1606
-
1607
- /**
1608
- * @param {string} regexString
1609
- * @param {string} [requiredFlags]
1610
- * @returns {RegExp}
1611
- */
1612
- exports.pathDoesNotBeginWith = pathDoesNotBeginWith;
1613
- const getRegexFromString = (regexString, requiredFlags) => {
1614
- const match = regexString.match(/^\/(.*)\/([gimyvus]*)$/vs);
1615
- let flags = 'v';
1616
- let regex = regexString;
1617
- if (match) {
1618
- [, regex, flags] = match;
1619
- if (!flags) {
1620
- flags = 'v';
1621
- }
1622
- }
1623
- const uniqueFlags = [...new Set(flags + (requiredFlags || ''))];
1624
- flags = uniqueFlags.join('');
1625
- return new RegExp(regex, flags);
1626
- };
1627
- exports.getRegexFromString = getRegexFromString;
1628
- const strictNativeTypes = exports.strictNativeTypes = ['undefined', 'null', 'boolean', 'number', 'bigint', 'string', 'symbol', 'object', 'Array', 'Function', 'Date', 'RegExp'];
1629
-
1630
- /**
1631
- * @param {import('@es-joy/jsdoccomment').JsdocBlockWithInline} jsdoc
1632
- * @param {import('@es-joy/jsdoccomment').JsdocTagWithInline} tag
1633
- * @param {import('jsdoc-type-pratt-parser').RootResult} parsedType
1634
- * @param {string} indent
1635
- * @param {string} typeBracketSpacing
1636
- */
1637
- const rewireByParsedType = (jsdoc, tag, parsedType, indent, typeBracketSpacing = '') => {
1638
- const typeLines = (0, _jsdoccomment.stringify)(parsedType).split('\n');
1639
- const firstTypeLine = typeLines.shift();
1640
- const lastTypeLine = typeLines.pop();
1641
- const beginNameOrDescIdx = tag.source.findIndex(({
1642
- tokens
1643
- }) => {
1644
- return tokens.name || tokens.description;
1645
- });
1646
- const nameAndDesc = beginNameOrDescIdx === -1 ? null : tag.source.slice(beginNameOrDescIdx);
1647
- const initialNumber = tag.source[0].number;
1648
- const src = [
1649
- // Get inevitably present tag from first `tag.source`
1650
- {
1651
- number: initialNumber,
1652
- source: '',
1653
- tokens: {
1654
- ...tag.source[0].tokens,
1655
- ...(typeLines.length || lastTypeLine ? {
1656
- end: '',
1657
- name: '',
1658
- postName: '',
1659
- postType: ''
1660
- } : nameAndDesc ? {
1661
- name: nameAndDesc[0].tokens.name,
1662
- postType: ' '
1663
- } : {}),
1664
- type: '{' + typeBracketSpacing + firstTypeLine + (!typeLines.length && lastTypeLine === undefined ? typeBracketSpacing + '}' : '')
1665
- }
1666
- },
1667
- // Get any intervening type lines
1668
- ...(typeLines.length ? typeLines.map((typeLine, idx) => {
1669
- return {
1670
- number: initialNumber + idx + 1,
1671
- source: '',
1672
- tokens: {
1673
- // Grab any delimiter info from first item
1674
- ...tag.source[0].tokens,
1675
- delimiter: tag.source[0].tokens.delimiter === '/**' ? '*' : tag.source[0].tokens.delimiter,
1676
- end: '',
1677
- name: '',
1678
- postName: '',
1679
- postTag: '',
1680
- postType: '',
1681
- start: indent + ' ',
1682
- tag: '',
1683
- type: typeLine
1684
- }
1685
- };
1686
- }) : [])];
1687
-
1688
- // Merge any final type line and name and description
1689
- if (
1690
- // Name and description may be already included if present with the tag
1691
- nameAndDesc && beginNameOrDescIdx > 0) {
1692
- if (typeLines.length || lastTypeLine !== undefined) {
1693
- src.push({
1694
- number: src.length + 1,
1695
- source: '',
1696
- tokens: {
1697
- ...nameAndDesc[0].tokens,
1698
- type: lastTypeLine + typeBracketSpacing + '}'
1699
- }
1700
- });
1701
- }
1702
- if (
1703
- // Get any remaining description lines
1704
- nameAndDesc.length > 1) {
1705
- src.push(...nameAndDesc.slice(1).map(({
1706
- source,
1707
- tokens
1708
- }, idx) => {
1709
- return {
1710
- number: src.length + idx + 2,
1711
- source,
1712
- tokens
1713
- };
1714
- }));
1715
- }
1716
- } else if (nameAndDesc) {
1717
- if ((typeLines.length || lastTypeLine !== undefined) && lastTypeLine) {
1718
- src.push({
1719
- number: src.length + 1,
1720
- source: '',
1721
- tokens: {
1722
- ...nameAndDesc[0].tokens,
1723
- delimiter: nameAndDesc[0].tokens.delimiter === '/**' ? '*' : nameAndDesc[0].tokens.delimiter,
1724
- postTag: '',
1725
- start: indent + ' ',
1726
- tag: '',
1727
- type: lastTypeLine + typeBracketSpacing + '}'
1728
- }
1729
- });
1730
- }
1731
- if (
1732
- // Get any remaining description lines
1733
- nameAndDesc.length > 1) {
1734
- src.push(...nameAndDesc.slice(1).map(({
1735
- source,
1736
- tokens
1737
- }, idx) => {
1738
- return {
1739
- number: src.length + idx + 2,
1740
- source,
1741
- tokens
1742
- };
1743
- }));
1744
- }
1745
- } else if (lastTypeLine) {
1746
- src.push({
1747
- number: src.length + 1,
1748
- source: '',
1749
- tokens: {
1750
- ...tag.source[0].tokens,
1751
- delimiter: tag.source[0].tokens.delimiter === '/**' ? '*' : tag.source[0].tokens.delimiter,
1752
- postTag: '',
1753
- start: indent + ' ',
1754
- tag: '',
1755
- type: lastTypeLine + typeBracketSpacing + '}'
1756
- }
1757
- });
1758
- }
1759
- tag.source = src;
1760
-
1761
- // Properly rewire `jsdoc.source`
1762
- const firstTagIdx = jsdoc.source.findIndex(({
1763
- tokens: {
1764
- tag: tg
1765
- }
1766
- }) => {
1767
- return tg;
1768
- });
1769
- const initialEndSource = jsdoc.source.find(({
1770
- tokens: {
1771
- end
1772
- }
1773
- }) => {
1774
- return end;
1775
- });
1776
- jsdoc.source = [...jsdoc.source.slice(0, firstTagIdx), ...jsdoc.tags.flatMap(({
1777
- source
1778
- }) => {
1779
- return source;
1780
- })];
1781
- if (initialEndSource && !jsdoc.source.at(-1)?.tokens?.end) {
1782
- jsdoc.source.push(initialEndSource);
1783
- }
1784
- };
1785
- exports.rewireByParsedType = rewireByParsedType;
1786
- //# sourceMappingURL=jsdocUtils.cjs.map