eslint-plugin-jsdoc 47.0.2 → 48.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/dist/{WarnSettings.js → WarnSettings.cjs} +2 -2
  2. package/dist/WarnSettings.cjs.map +1 -0
  3. package/dist/{alignTransform.js → alignTransform.cjs} +2 -2
  4. package/dist/alignTransform.cjs.map +1 -0
  5. package/dist/{defaultTagOrder.js → defaultTagOrder.cjs} +1 -1
  6. package/dist/defaultTagOrder.cjs.map +1 -0
  7. package/dist/{exportParser.js → exportParser.cjs} +32 -36
  8. package/dist/exportParser.cjs.map +1 -0
  9. package/dist/{generateRule.js → generateRule.cjs} +7 -4
  10. package/dist/generateRule.cjs.map +1 -0
  11. package/dist/{getDefaultTagStructureForMode.js → getDefaultTagStructureForMode.cjs} +1 -1
  12. package/dist/getDefaultTagStructureForMode.cjs.map +1 -0
  13. package/dist/{index.js → index.cjs} +55 -55
  14. package/dist/index.cjs.map +1 -0
  15. package/dist/{iterateJsdoc.js → iterateJsdoc.cjs} +16 -21
  16. package/dist/iterateJsdoc.cjs.map +1 -0
  17. package/dist/{jsdocUtils.js → jsdocUtils.cjs} +17 -17
  18. package/dist/jsdocUtils.cjs.map +1 -0
  19. package/dist/rules/{checkAccess.js → checkAccess.cjs} +2 -2
  20. package/dist/rules/checkAccess.cjs.map +1 -0
  21. package/dist/rules/{checkAlignment.js → checkAlignment.cjs} +2 -2
  22. package/dist/rules/checkAlignment.cjs.map +1 -0
  23. package/dist/rules/{checkExamples.js → checkExamples.cjs} +2 -2
  24. package/dist/rules/checkExamples.cjs.map +1 -0
  25. package/dist/rules/{checkIndentation.js → checkIndentation.cjs} +2 -2
  26. package/dist/rules/checkIndentation.cjs.map +1 -0
  27. package/dist/rules/{checkLineAlignment.js → checkLineAlignment.cjs} +3 -3
  28. package/dist/rules/checkLineAlignment.cjs.map +1 -0
  29. package/dist/rules/{checkParamNames.js → checkParamNames.cjs} +2 -2
  30. package/dist/rules/checkParamNames.cjs.map +1 -0
  31. package/dist/rules/{checkPropertyNames.js → checkPropertyNames.cjs} +2 -2
  32. package/dist/rules/checkPropertyNames.cjs.map +1 -0
  33. package/dist/rules/{checkSyntax.js → checkSyntax.cjs} +2 -2
  34. package/dist/rules/checkSyntax.cjs.map +1 -0
  35. package/dist/rules/{checkTagNames.js → checkTagNames.cjs} +2 -2
  36. package/dist/rules/checkTagNames.cjs.map +1 -0
  37. package/dist/rules/{checkTypes.js → checkTypes.cjs} +2 -2
  38. package/dist/rules/checkTypes.cjs.map +1 -0
  39. package/dist/rules/{checkValues.js → checkValues.cjs} +2 -2
  40. package/dist/rules/checkValues.cjs.map +1 -0
  41. package/dist/rules/{emptyTags.js → emptyTags.cjs} +2 -2
  42. package/dist/rules/emptyTags.cjs.map +1 -0
  43. package/dist/rules/{implementsOnClasses.js → implementsOnClasses.cjs} +2 -2
  44. package/dist/rules/implementsOnClasses.cjs.map +1 -0
  45. package/dist/rules/{importsAsDependencies.js → importsAsDependencies.cjs} +10 -12
  46. package/dist/rules/importsAsDependencies.cjs.map +1 -0
  47. package/dist/rules/{informativeDocs.js → informativeDocs.cjs} +2 -2
  48. package/dist/rules/informativeDocs.cjs.map +1 -0
  49. package/dist/rules/{matchDescription.js → matchDescription.cjs} +2 -2
  50. package/dist/rules/matchDescription.cjs.map +1 -0
  51. package/dist/rules/{matchName.js → matchName.cjs} +2 -2
  52. package/dist/rules/matchName.cjs.map +1 -0
  53. package/dist/rules/{multilineBlocks.js → multilineBlocks.cjs} +2 -2
  54. package/dist/rules/multilineBlocks.cjs.map +1 -0
  55. package/dist/rules/{noBadBlocks.js → noBadBlocks.cjs} +2 -2
  56. package/dist/rules/noBadBlocks.cjs.map +1 -0
  57. package/dist/rules/{noBlankBlockDescriptions.js → noBlankBlockDescriptions.cjs} +2 -2
  58. package/dist/rules/noBlankBlockDescriptions.cjs.map +1 -0
  59. package/dist/rules/{noBlankBlocks.js → noBlankBlocks.cjs} +2 -2
  60. package/dist/rules/noBlankBlocks.cjs.map +1 -0
  61. package/dist/rules/{noDefaults.js → noDefaults.cjs} +2 -2
  62. package/dist/rules/noDefaults.cjs.map +1 -0
  63. package/dist/rules/{noMissingSyntax.js → noMissingSyntax.cjs} +2 -2
  64. package/dist/rules/noMissingSyntax.cjs.map +1 -0
  65. package/dist/rules/{noMultiAsterisks.js → noMultiAsterisks.cjs} +2 -2
  66. package/dist/rules/noMultiAsterisks.cjs.map +1 -0
  67. package/dist/rules/{noRestrictedSyntax.js → noRestrictedSyntax.cjs} +2 -2
  68. package/dist/rules/noRestrictedSyntax.cjs.map +1 -0
  69. package/dist/rules/{noTypes.js → noTypes.cjs} +2 -2
  70. package/dist/rules/noTypes.cjs.map +1 -0
  71. package/dist/rules/{noUndefinedTypes.js → noUndefinedTypes.cjs} +5 -5
  72. package/dist/rules/noUndefinedTypes.cjs.map +1 -0
  73. package/dist/rules/{requireAsteriskPrefix.js → requireAsteriskPrefix.cjs} +2 -2
  74. package/dist/rules/requireAsteriskPrefix.cjs.map +1 -0
  75. package/dist/rules/{requireDescription.js → requireDescription.cjs} +2 -2
  76. package/dist/rules/requireDescription.cjs.map +1 -0
  77. package/dist/rules/{requireDescriptionCompleteSentence.js → requireDescriptionCompleteSentence.cjs} +2 -2
  78. package/dist/rules/requireDescriptionCompleteSentence.cjs.map +1 -0
  79. package/dist/rules/{requireExample.js → requireExample.cjs} +2 -2
  80. package/dist/rules/requireExample.cjs.map +1 -0
  81. package/dist/rules/{requireFileOverview.js → requireFileOverview.cjs} +2 -2
  82. package/dist/rules/requireFileOverview.cjs.map +1 -0
  83. package/dist/rules/{requireHyphenBeforeParamDescription.js → requireHyphenBeforeParamDescription.cjs} +2 -2
  84. package/dist/rules/requireHyphenBeforeParamDescription.cjs.map +1 -0
  85. package/dist/rules/{requireJsdoc.js → requireJsdoc.cjs} +5 -5
  86. package/dist/rules/requireJsdoc.cjs.map +1 -0
  87. package/dist/rules/{requireParam.js → requireParam.cjs} +2 -2
  88. package/dist/rules/requireParam.cjs.map +1 -0
  89. package/dist/rules/{requireParamDescription.js → requireParamDescription.cjs} +2 -2
  90. package/dist/rules/requireParamDescription.cjs.map +1 -0
  91. package/dist/rules/{requireParamName.js → requireParamName.cjs} +2 -2
  92. package/dist/rules/requireParamName.cjs.map +1 -0
  93. package/dist/rules/{requireParamType.js → requireParamType.cjs} +2 -2
  94. package/dist/rules/requireParamType.cjs.map +1 -0
  95. package/dist/rules/{requireProperty.js → requireProperty.cjs} +2 -2
  96. package/dist/rules/requireProperty.cjs.map +1 -0
  97. package/dist/rules/{requirePropertyDescription.js → requirePropertyDescription.cjs} +2 -2
  98. package/dist/rules/requirePropertyDescription.cjs.map +1 -0
  99. package/dist/rules/{requirePropertyName.js → requirePropertyName.cjs} +2 -2
  100. package/dist/rules/requirePropertyName.cjs.map +1 -0
  101. package/dist/rules/{requirePropertyType.js → requirePropertyType.cjs} +2 -2
  102. package/dist/rules/requirePropertyType.cjs.map +1 -0
  103. package/dist/rules/{requireReturns.js → requireReturns.cjs} +4 -4
  104. package/dist/rules/requireReturns.cjs.map +1 -0
  105. package/dist/rules/{requireReturnsCheck.js → requireReturnsCheck.cjs} +2 -2
  106. package/dist/rules/requireReturnsCheck.cjs.map +1 -0
  107. package/dist/rules/{requireReturnsDescription.js → requireReturnsDescription.cjs} +2 -2
  108. package/dist/rules/requireReturnsDescription.cjs.map +1 -0
  109. package/dist/rules/{requireReturnsType.js → requireReturnsType.cjs} +2 -2
  110. package/dist/rules/requireReturnsType.cjs.map +1 -0
  111. package/dist/rules/{requireThrows.js → requireThrows.cjs} +2 -2
  112. package/dist/rules/requireThrows.cjs.map +1 -0
  113. package/dist/rules/{requireYields.js → requireYields.cjs} +2 -2
  114. package/dist/rules/requireYields.cjs.map +1 -0
  115. package/dist/rules/{requireYieldsCheck.js → requireYieldsCheck.cjs} +2 -2
  116. package/dist/rules/requireYieldsCheck.cjs.map +1 -0
  117. package/dist/rules/{sortTags.js → sortTags.cjs} +4 -4
  118. package/dist/rules/sortTags.cjs.map +1 -0
  119. package/dist/rules/{tagLines.js → tagLines.cjs} +2 -2
  120. package/dist/rules/tagLines.cjs.map +1 -0
  121. package/dist/rules/{textEscaping.js → textEscaping.cjs} +2 -2
  122. package/dist/rules/textEscaping.cjs.map +1 -0
  123. package/dist/rules/{validTypes.js → validTypes.cjs} +2 -2
  124. package/dist/rules/validTypes.cjs.map +1 -0
  125. package/dist/{tagNames.js → tagNames.cjs} +1 -1
  126. package/dist/tagNames.cjs.map +1 -0
  127. package/dist/utils/{hasReturnValue.js → hasReturnValue.cjs} +14 -17
  128. package/dist/utils/hasReturnValue.cjs.map +1 -0
  129. package/{eslint.config.mjs → eslint.config.js} +34 -28
  130. package/package.json +15 -15
  131. package/src/WarnSettings.js +34 -0
  132. package/src/alignTransform.js +356 -0
  133. package/src/defaultTagOrder.js +168 -0
  134. package/src/exportParser.js +957 -0
  135. package/src/getDefaultTagStructureForMode.js +969 -0
  136. package/src/index.js +266 -0
  137. package/src/iterateJsdoc.js +2555 -0
  138. package/src/jsdocUtils.js +1693 -0
  139. package/src/rules/checkAccess.js +45 -0
  140. package/src/rules/checkAlignment.js +63 -0
  141. package/src/rules/checkExamples.js +594 -0
  142. package/src/rules/checkIndentation.js +75 -0
  143. package/src/rules/checkLineAlignment.js +364 -0
  144. package/src/rules/checkParamNames.js +404 -0
  145. package/src/rules/checkPropertyNames.js +152 -0
  146. package/src/rules/checkSyntax.js +30 -0
  147. package/src/rules/checkTagNames.js +314 -0
  148. package/src/rules/checkTypes.js +535 -0
  149. package/src/rules/checkValues.js +220 -0
  150. package/src/rules/emptyTags.js +88 -0
  151. package/src/rules/implementsOnClasses.js +64 -0
  152. package/src/rules/importsAsDependencies.js +131 -0
  153. package/src/rules/informativeDocs.js +182 -0
  154. package/src/rules/matchDescription.js +286 -0
  155. package/src/rules/matchName.js +147 -0
  156. package/src/rules/multilineBlocks.js +333 -0
  157. package/src/rules/noBadBlocks.js +109 -0
  158. package/src/rules/noBlankBlockDescriptions.js +69 -0
  159. package/src/rules/noBlankBlocks.js +53 -0
  160. package/src/rules/noDefaults.js +85 -0
  161. package/src/rules/noMissingSyntax.js +195 -0
  162. package/src/rules/noMultiAsterisks.js +134 -0
  163. package/src/rules/noRestrictedSyntax.js +91 -0
  164. package/src/rules/noTypes.js +73 -0
  165. package/src/rules/noUndefinedTypes.js +328 -0
  166. package/src/rules/requireAsteriskPrefix.js +189 -0
  167. package/src/rules/requireDescription.js +161 -0
  168. package/src/rules/requireDescriptionCompleteSentence.js +333 -0
  169. package/src/rules/requireExample.js +118 -0
  170. package/src/rules/requireFileOverview.js +154 -0
  171. package/src/rules/requireHyphenBeforeParamDescription.js +178 -0
  172. package/src/rules/requireJsdoc.js +629 -0
  173. package/src/rules/requireParam.js +592 -0
  174. package/src/rules/requireParamDescription.js +89 -0
  175. package/src/rules/requireParamName.js +55 -0
  176. package/src/rules/requireParamType.js +89 -0
  177. package/src/rules/requireProperty.js +48 -0
  178. package/src/rules/requirePropertyDescription.js +25 -0
  179. package/src/rules/requirePropertyName.js +25 -0
  180. package/src/rules/requirePropertyType.js +25 -0
  181. package/src/rules/requireReturns.js +238 -0
  182. package/src/rules/requireReturnsCheck.js +141 -0
  183. package/src/rules/requireReturnsDescription.js +59 -0
  184. package/src/rules/requireReturnsType.js +51 -0
  185. package/src/rules/requireThrows.js +111 -0
  186. package/src/rules/requireYields.js +216 -0
  187. package/src/rules/requireYieldsCheck.js +208 -0
  188. package/src/rules/sortTags.js +557 -0
  189. package/src/rules/tagLines.js +359 -0
  190. package/src/rules/textEscaping.js +146 -0
  191. package/src/rules/validTypes.js +368 -0
  192. package/src/tagNames.js +234 -0
  193. package/src/utils/hasReturnValue.js +549 -0
  194. package/dist/WarnSettings.js.map +0 -1
  195. package/dist/alignTransform.js.map +0 -1
  196. package/dist/defaultTagOrder.js.map +0 -1
  197. package/dist/exportParser.js.map +0 -1
  198. package/dist/generateRule.js.map +0 -1
  199. package/dist/getDefaultTagStructureForMode.js.map +0 -1
  200. package/dist/index.js.map +0 -1
  201. package/dist/iterateJsdoc.js.map +0 -1
  202. package/dist/jsdocUtils.js.map +0 -1
  203. package/dist/rules/checkAccess.js.map +0 -1
  204. package/dist/rules/checkAlignment.js.map +0 -1
  205. package/dist/rules/checkExamples.js.map +0 -1
  206. package/dist/rules/checkIndentation.js.map +0 -1
  207. package/dist/rules/checkLineAlignment.js.map +0 -1
  208. package/dist/rules/checkParamNames.js.map +0 -1
  209. package/dist/rules/checkPropertyNames.js.map +0 -1
  210. package/dist/rules/checkSyntax.js.map +0 -1
  211. package/dist/rules/checkTagNames.js.map +0 -1
  212. package/dist/rules/checkTypes.js.map +0 -1
  213. package/dist/rules/checkValues.js.map +0 -1
  214. package/dist/rules/emptyTags.js.map +0 -1
  215. package/dist/rules/implementsOnClasses.js.map +0 -1
  216. package/dist/rules/importsAsDependencies.js.map +0 -1
  217. package/dist/rules/informativeDocs.js.map +0 -1
  218. package/dist/rules/matchDescription.js.map +0 -1
  219. package/dist/rules/matchName.js.map +0 -1
  220. package/dist/rules/multilineBlocks.js.map +0 -1
  221. package/dist/rules/noBadBlocks.js.map +0 -1
  222. package/dist/rules/noBlankBlockDescriptions.js.map +0 -1
  223. package/dist/rules/noBlankBlocks.js.map +0 -1
  224. package/dist/rules/noDefaults.js.map +0 -1
  225. package/dist/rules/noMissingSyntax.js.map +0 -1
  226. package/dist/rules/noMultiAsterisks.js.map +0 -1
  227. package/dist/rules/noRestrictedSyntax.js.map +0 -1
  228. package/dist/rules/noTypes.js.map +0 -1
  229. package/dist/rules/noUndefinedTypes.js.map +0 -1
  230. package/dist/rules/requireAsteriskPrefix.js.map +0 -1
  231. package/dist/rules/requireDescription.js.map +0 -1
  232. package/dist/rules/requireDescriptionCompleteSentence.js.map +0 -1
  233. package/dist/rules/requireExample.js.map +0 -1
  234. package/dist/rules/requireFileOverview.js.map +0 -1
  235. package/dist/rules/requireHyphenBeforeParamDescription.js.map +0 -1
  236. package/dist/rules/requireJsdoc.js.map +0 -1
  237. package/dist/rules/requireParam.js.map +0 -1
  238. package/dist/rules/requireParamDescription.js.map +0 -1
  239. package/dist/rules/requireParamName.js.map +0 -1
  240. package/dist/rules/requireParamType.js.map +0 -1
  241. package/dist/rules/requireProperty.js.map +0 -1
  242. package/dist/rules/requirePropertyDescription.js.map +0 -1
  243. package/dist/rules/requirePropertyName.js.map +0 -1
  244. package/dist/rules/requirePropertyType.js.map +0 -1
  245. package/dist/rules/requireReturns.js.map +0 -1
  246. package/dist/rules/requireReturnsCheck.js.map +0 -1
  247. package/dist/rules/requireReturnsDescription.js.map +0 -1
  248. package/dist/rules/requireReturnsType.js.map +0 -1
  249. package/dist/rules/requireThrows.js.map +0 -1
  250. package/dist/rules/requireYields.js.map +0 -1
  251. package/dist/rules/requireYieldsCheck.js.map +0 -1
  252. package/dist/rules/sortTags.js.map +0 -1
  253. package/dist/rules/tagLines.js.map +0 -1
  254. package/dist/rules/textEscaping.js.map +0 -1
  255. package/dist/rules/validTypes.js.map +0 -1
  256. package/dist/tagNames.js.map +0 -1
  257. package/dist/utils/hasReturnValue.js.map +0 -1
@@ -0,0 +1,368 @@
1
+ import iterateJsdoc from '../iterateJsdoc.js';
2
+ import {
3
+ parse,
4
+ traverse,
5
+ tryParse,
6
+ } from '@es-joy/jsdoccomment';
7
+
8
+ const inlineTags = new Set([
9
+ 'link', 'linkcode', 'linkplain',
10
+ 'tutorial',
11
+ ]);
12
+
13
+ const asExpression = /as\s+/u;
14
+
15
+ const suppressTypes = new Set([
16
+ // https://github.com/google/closure-compiler/wiki/@suppress-annotations
17
+ // https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/parsing/ParserConfig.properties#L154
18
+ 'accessControls',
19
+ 'checkDebuggerStatement',
20
+ 'checkPrototypalTypes',
21
+ 'checkRegExp',
22
+ 'checkTypes',
23
+ 'checkVars',
24
+ 'closureDepMethodUsageChecks',
25
+ 'const',
26
+ 'constantProperty',
27
+ 'deprecated',
28
+ 'duplicate',
29
+ 'es5Strict',
30
+ 'externsValidation',
31
+ 'extraProvide',
32
+ 'extraRequire',
33
+ 'globalThis',
34
+ 'invalidCasts',
35
+ 'lateProvide',
36
+ 'legacyGoogScopeRequire',
37
+ 'lintChecks',
38
+ 'messageConventions',
39
+ 'misplacedTypeAnnotation',
40
+ 'missingOverride',
41
+ 'missingPolyfill',
42
+ 'missingProperties',
43
+ 'missingProvide',
44
+ 'missingRequire',
45
+ 'missingSourcesWarnings',
46
+ 'moduleLoad',
47
+ 'nonStandardJsDocs',
48
+ 'partialAlias',
49
+ 'polymer',
50
+ 'reportUnknownTypes',
51
+ 'strictMissingProperties',
52
+ 'strictModuleDepCheck',
53
+ 'strictPrimitiveOperators',
54
+ 'suspiciousCode',
55
+
56
+ // Not documented in enum
57
+ 'switch',
58
+ 'transitionalSuspiciousCodeWarnings',
59
+ 'undefinedNames',
60
+ 'undefinedVars',
61
+ 'underscore',
62
+ 'unknownDefines',
63
+ 'untranspilableFeatures',
64
+ 'unusedLocalVariables',
65
+ 'unusedPrivateMembers',
66
+ 'useOfGoogProvide',
67
+ 'uselessCode',
68
+ 'visibility',
69
+ 'with',
70
+ ]);
71
+
72
+ /**
73
+ * @param {string} path
74
+ * @returns {boolean}
75
+ */
76
+ const tryParsePathIgnoreError = (path) => {
77
+ try {
78
+ tryParse(path);
79
+
80
+ return true;
81
+ } catch {
82
+ // Keep the original error for including the whole type
83
+ }
84
+
85
+ return false;
86
+ };
87
+
88
+ // eslint-disable-next-line complexity
89
+ export default iterateJsdoc(({
90
+ jsdoc,
91
+ report,
92
+ utils,
93
+ context,
94
+ settings,
95
+ }) => {
96
+ const {
97
+ allowEmptyNamepaths = false,
98
+ } = context.options[0] || {};
99
+ const {
100
+ mode,
101
+ } = settings;
102
+
103
+ for (const tag of jsdoc.tags) {
104
+ /**
105
+ * @param {string} namepath
106
+ * @param {string} [tagName]
107
+ * @returns {boolean}
108
+ */
109
+ const validNamepathParsing = function (namepath, tagName) {
110
+ if (tryParsePathIgnoreError(namepath)) {
111
+ return true;
112
+ }
113
+
114
+ let handled = false;
115
+
116
+ if (tagName) {
117
+ switch (tagName) {
118
+ case 'requires':
119
+ case 'module': {
120
+ if (!namepath.startsWith('module:')) {
121
+ handled = tryParsePathIgnoreError(`module:${namepath}`);
122
+ }
123
+
124
+ break;
125
+ }
126
+
127
+ case 'memberof': case 'memberof!': {
128
+ const endChar = namepath.slice(-1);
129
+ if ([
130
+ '#', '.', '~',
131
+ ].includes(endChar)) {
132
+ handled = tryParsePathIgnoreError(namepath.slice(0, -1));
133
+ }
134
+
135
+ break;
136
+ }
137
+
138
+ case 'borrows': {
139
+ const startChar = namepath.charAt(0);
140
+ if ([
141
+ '#', '.', '~',
142
+ ].includes(startChar)) {
143
+ handled = tryParsePathIgnoreError(namepath.slice(1));
144
+ }
145
+ }
146
+ }
147
+ }
148
+
149
+ if (!handled) {
150
+ report(`Syntax error in namepath: ${namepath}`, null, tag);
151
+
152
+ return false;
153
+ }
154
+
155
+ return true;
156
+ };
157
+
158
+ /**
159
+ * @param {string} type
160
+ * @returns {boolean}
161
+ */
162
+ const validTypeParsing = function (type) {
163
+ let parsedTypes;
164
+ try {
165
+ if (mode === 'permissive') {
166
+ parsedTypes = tryParse(type);
167
+ } else {
168
+ parsedTypes = parse(type, mode);
169
+ }
170
+ } catch {
171
+ report(`Syntax error in type: ${type}`, null, tag);
172
+
173
+ return false;
174
+ }
175
+
176
+ if (mode === 'closure' || mode === 'typescript') {
177
+ traverse(parsedTypes, (node) => {
178
+ const {
179
+ type: typ,
180
+ } = node;
181
+
182
+ if (
183
+ (typ === 'JsdocTypeObjectField' || typ === 'JsdocTypeKeyValue') &&
184
+ node.right?.type === 'JsdocTypeNullable' &&
185
+ node.right?.meta?.position === 'suffix'
186
+ ) {
187
+ report(`Syntax error in type: ${node.right.type}`, null, tag);
188
+ }
189
+ });
190
+ }
191
+
192
+ return true;
193
+ };
194
+
195
+ if (tag.problems.length) {
196
+ const msg = tag.problems.reduce((str, {
197
+ message,
198
+ }) => {
199
+ return str + '; ' + message;
200
+ }, '').slice(2);
201
+ report(`Invalid name: ${msg}`, null, tag);
202
+ continue;
203
+ }
204
+
205
+ if (tag.tag === 'borrows') {
206
+ const thisNamepath = /** @type {string} */ (
207
+ utils.getTagDescription(tag)
208
+ ).replace(asExpression, '')
209
+ .trim();
210
+
211
+ if (!asExpression.test(/** @type {string} */ (
212
+ utils.getTagDescription(tag)
213
+ )) || !thisNamepath) {
214
+ report(`@borrows must have an "as" expression. Found "${utils.getTagDescription(tag)}"`, null, tag);
215
+
216
+ continue;
217
+ }
218
+
219
+ if (validNamepathParsing(thisNamepath, 'borrows')) {
220
+ const thatNamepath = tag.name;
221
+
222
+ validNamepathParsing(thatNamepath);
223
+ }
224
+
225
+ continue;
226
+ }
227
+
228
+ if (tag.tag === 'suppress' && mode === 'closure') {
229
+ let parsedTypes;
230
+
231
+ try {
232
+ parsedTypes = tryParse(tag.type);
233
+ } catch {
234
+ // Ignore
235
+ }
236
+
237
+ if (parsedTypes) {
238
+ traverse(parsedTypes, (node) => {
239
+ let type;
240
+ if ('value' in node && typeof node.value === 'string') {
241
+ type = node.value;
242
+ }
243
+
244
+ if (type !== undefined && !suppressTypes.has(type)) {
245
+ report(`Syntax error in suppress type: ${type}`, null, tag);
246
+ }
247
+ });
248
+ }
249
+ }
250
+
251
+ const otherModeMaps = /** @type {import('../jsdocUtils.js').ParserMode[]} */ ([
252
+ 'jsdoc', 'typescript', 'closure', 'permissive',
253
+ ]).filter(
254
+ (mde) => {
255
+ return mde !== mode;
256
+ },
257
+ ).map((mde) => {
258
+ return utils.getTagStructureForMode(mde);
259
+ });
260
+
261
+ const tagMightHaveNamePosition = utils.tagMightHaveNamePosition(tag.tag, otherModeMaps);
262
+ if (tagMightHaveNamePosition !== true && tag.name) {
263
+ const modeInfo = tagMightHaveNamePosition === false ? '' : ` in "${mode}" mode`;
264
+ report(`@${tag.tag} should not have a name${modeInfo}.`, null, tag);
265
+
266
+ continue;
267
+ }
268
+
269
+ const mightHaveTypePosition = utils.tagMightHaveTypePosition(tag.tag, otherModeMaps);
270
+ if (mightHaveTypePosition !== true && tag.type) {
271
+ const modeInfo = mightHaveTypePosition === false ? '' : ` in "${mode}" mode`;
272
+ report(`@${tag.tag} should not have a bracketed type${modeInfo}.`, null, tag);
273
+
274
+ continue;
275
+ }
276
+
277
+ // REQUIRED NAME
278
+ const tagMustHaveNamePosition = utils.tagMustHaveNamePosition(tag.tag, otherModeMaps);
279
+
280
+ // Don't handle `@param` here though it does require name as handled by
281
+ // `require-param-name` (`@property` would similarly seem to require one,
282
+ // but is handled by `require-property-name`)
283
+ if (tagMustHaveNamePosition !== false && !tag.name && !allowEmptyNamepaths && ![
284
+ 'param', 'arg', 'argument',
285
+ 'property', 'prop',
286
+ ].includes(tag.tag) &&
287
+ (tag.tag !== 'see' || !utils.getTagDescription(tag).includes('{@link'))
288
+ ) {
289
+ const modeInfo = tagMustHaveNamePosition === true ? '' : ` in "${mode}" mode`;
290
+ report(`Tag @${tag.tag} must have a name/namepath${modeInfo}.`, null, tag);
291
+
292
+ continue;
293
+ }
294
+
295
+ // REQUIRED TYPE
296
+ const mustHaveTypePosition = utils.tagMustHaveTypePosition(tag.tag, otherModeMaps);
297
+ if (mustHaveTypePosition !== false && !tag.type) {
298
+ const modeInfo = mustHaveTypePosition === true ? '' : ` in "${mode}" mode`;
299
+ report(`Tag @${tag.tag} must have a type${modeInfo}.`, null, tag);
300
+
301
+ continue;
302
+ }
303
+
304
+ // REQUIRED TYPE OR NAME/NAMEPATH
305
+ const tagMissingRequiredTypeOrNamepath = utils.tagMissingRequiredTypeOrNamepath(tag, otherModeMaps);
306
+ if (tagMissingRequiredTypeOrNamepath !== false && !allowEmptyNamepaths) {
307
+ const modeInfo = tagMissingRequiredTypeOrNamepath === true ? '' : ` in "${mode}" mode`;
308
+ report(`Tag @${tag.tag} must have either a type or namepath${modeInfo}.`, null, tag);
309
+
310
+ continue;
311
+ }
312
+
313
+ // VALID TYPE
314
+ const hasTypePosition = mightHaveTypePosition === true && Boolean(tag.type);
315
+ if (hasTypePosition) {
316
+ validTypeParsing(tag.type);
317
+ }
318
+
319
+ // VALID NAME/NAMEPATH
320
+ const hasNameOrNamepathPosition = (
321
+ tagMustHaveNamePosition !== false ||
322
+ utils.tagMightHaveNamepath(tag.tag)
323
+ ) && Boolean(tag.name);
324
+
325
+ if (hasNameOrNamepathPosition) {
326
+ if (mode !== 'jsdoc' && tag.tag === 'template') {
327
+ for (const namepath of utils.parseClosureTemplateTag(tag)) {
328
+ validNamepathParsing(namepath);
329
+ }
330
+ } else {
331
+ validNamepathParsing(tag.name, tag.tag);
332
+ }
333
+ }
334
+
335
+ for (const inlineTag of tag.inlineTags) {
336
+ if (inlineTags.has(inlineTag.tag) && !inlineTag.text && !inlineTag.namepathOrURL) {
337
+ report(`Inline tag "${inlineTag.tag}" missing content`, null, tag);
338
+ }
339
+ }
340
+ }
341
+
342
+ for (const inlineTag of jsdoc.inlineTags) {
343
+ if (inlineTags.has(inlineTag.tag) && !inlineTag.text && !inlineTag.namepathOrURL) {
344
+ report(`Inline tag "${inlineTag.tag}" missing content`);
345
+ }
346
+ }
347
+ }, {
348
+ iterateAllJsdocs: true,
349
+ meta: {
350
+ docs: {
351
+ description: 'Requires all types to be valid JSDoc or Closure compiler types without syntax errors.',
352
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/valid-types.md#repos-sticky-header',
353
+ },
354
+ schema: [
355
+ {
356
+ additionalProperties: false,
357
+ properties: {
358
+ allowEmptyNamepaths: {
359
+ default: false,
360
+ type: 'boolean',
361
+ },
362
+ },
363
+ type: 'object',
364
+ },
365
+ ],
366
+ type: 'suggestion',
367
+ },
368
+ });
@@ -0,0 +1,234 @@
1
+ /**
2
+ * @typedef {{
3
+ * [key: string]: string[]
4
+ * }} AliasedTags
5
+ */
6
+
7
+ /**
8
+ * @type {AliasedTags}
9
+ */
10
+ const jsdocTagsUndocumented = {
11
+ // Undocumented but present; see
12
+ // https://github.com/jsdoc/jsdoc/issues/1283#issuecomment-516816802
13
+ // https://github.com/jsdoc/jsdoc/blob/master/packages/jsdoc/lib/jsdoc/tag/dictionary/definitions.js#L594
14
+ modifies: [],
15
+ };
16
+
17
+ /**
18
+ * @type {AliasedTags}
19
+ */
20
+ const jsdocTags = {
21
+ ...jsdocTagsUndocumented,
22
+ abstract: [
23
+ 'virtual',
24
+ ],
25
+ access: [],
26
+ alias: [],
27
+ async: [],
28
+ augments: [
29
+ 'extends',
30
+ ],
31
+ author: [],
32
+ borrows: [],
33
+ callback: [],
34
+ class: [
35
+ 'constructor',
36
+ ],
37
+ classdesc: [],
38
+ constant: [
39
+ 'const',
40
+ ],
41
+ constructs: [],
42
+ copyright: [],
43
+ default: [
44
+ 'defaultvalue',
45
+ ],
46
+ deprecated: [],
47
+ description: [
48
+ 'desc',
49
+ ],
50
+ enum: [],
51
+ event: [],
52
+ example: [],
53
+ exports: [],
54
+ external: [
55
+ 'host',
56
+ ],
57
+ file: [
58
+ 'fileoverview',
59
+ 'overview',
60
+ ],
61
+ fires: [
62
+ 'emits',
63
+ ],
64
+ function: [
65
+ 'func',
66
+ 'method',
67
+ ],
68
+ generator: [],
69
+ global: [],
70
+ hideconstructor: [],
71
+ ignore: [],
72
+ implements: [],
73
+ inheritdoc: [],
74
+
75
+ // Allowing casing distinct from jsdoc `definitions.js` (required in Closure)
76
+ inheritDoc: [],
77
+
78
+ inner: [],
79
+ instance: [],
80
+ interface: [],
81
+ kind: [],
82
+ lends: [],
83
+ license: [],
84
+ listens: [],
85
+ member: [
86
+ 'var',
87
+ ],
88
+ memberof: [],
89
+ 'memberof!': [],
90
+ mixes: [],
91
+ mixin: [],
92
+
93
+ module: [],
94
+ name: [],
95
+ namespace: [],
96
+ override: [],
97
+ package: [],
98
+ param: [
99
+ 'arg',
100
+ 'argument',
101
+ ],
102
+ private: [],
103
+ property: [
104
+ 'prop',
105
+ ],
106
+ protected: [],
107
+ public: [],
108
+ readonly: [],
109
+ requires: [],
110
+ returns: [
111
+ 'return',
112
+ ],
113
+ see: [],
114
+ since: [],
115
+ static: [],
116
+ summary: [],
117
+
118
+ this: [],
119
+ throws: [
120
+ 'exception',
121
+ ],
122
+ todo: [],
123
+ tutorial: [],
124
+ type: [],
125
+ typedef: [],
126
+ variation: [],
127
+ version: [],
128
+ yields: [
129
+ 'yield',
130
+ ],
131
+ };
132
+
133
+ /**
134
+ * @type {AliasedTags}
135
+ */
136
+ const typeScriptTags = {
137
+ ...jsdocTags,
138
+
139
+ // https://www.typescriptlang.org/tsconfig/#stripInternal
140
+ internal: [],
141
+
142
+ // https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#overload-support-in-jsdoc
143
+ overload: [],
144
+
145
+ // https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#satisfies-support-in-jsdoc
146
+ satisfies: [],
147
+
148
+ // `@template` is also in TypeScript per:
149
+ // https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html#supported-jsdoc
150
+ template: [],
151
+ };
152
+
153
+ /**
154
+ * @type {AliasedTags}
155
+ */
156
+ const undocumentedClosureTags = {
157
+ // These are in Closure source but not in jsdoc source nor in the Closure
158
+ // docs: https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/parsing/Annotation.java
159
+ closurePrimitive: [],
160
+ customElement: [],
161
+ expose: [],
162
+ hidden: [],
163
+ idGenerator: [],
164
+ meaning: [],
165
+ mixinClass: [],
166
+ mixinFunction: [],
167
+ ngInject: [],
168
+ owner: [],
169
+ typeSummary: [],
170
+ wizaction: [],
171
+ };
172
+
173
+ const {
174
+ /* eslint-disable no-unused-vars */
175
+ inheritdoc,
176
+ internal,
177
+ overload,
178
+ satisfies,
179
+
180
+ // Will be inverted to prefer `return`
181
+ returns,
182
+ /* eslint-enable no-unused-vars */
183
+ ...typeScriptTagsInClosure
184
+ } = typeScriptTags;
185
+
186
+ /**
187
+ * @type {AliasedTags}
188
+ */
189
+ const closureTags = {
190
+ ...typeScriptTagsInClosure,
191
+ ...undocumentedClosureTags,
192
+
193
+ // From https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler
194
+ // These are all recognized in https://github.com/jsdoc/jsdoc/blob/master/packages/jsdoc/lib/jsdoc/tag/dictionary/definitions.js
195
+ // except for the experimental `noinline` and the casing differences noted below
196
+
197
+ // Defined as a synonym of `const` in jsdoc `definitions.js`
198
+ define: [],
199
+
200
+ dict: [],
201
+ export: [],
202
+ externs: [],
203
+ final: [],
204
+
205
+ // With casing distinct from jsdoc `definitions.js`
206
+ implicitCast: [],
207
+
208
+ noalias: [],
209
+ nocollapse: [],
210
+ nocompile: [],
211
+ noinline: [],
212
+ nosideeffects: [],
213
+ polymer: [],
214
+ polymerBehavior: [],
215
+ preserve: [],
216
+
217
+ // Defined as a synonym of `interface` in jsdoc `definitions.js`
218
+ record: [],
219
+
220
+ return: [
221
+ 'returns',
222
+ ],
223
+
224
+ struct: [],
225
+ suppress: [],
226
+
227
+ unrestricted: [],
228
+ };
229
+
230
+ export {
231
+ closureTags,
232
+ jsdocTags,
233
+ typeScriptTags,
234
+ };