eslint-plugin-jsdoc 48.0.0 → 48.0.2

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 (64) hide show
  1. package/package.json +2 -2
  2. package/src/WarnSettings.js +34 -0
  3. package/src/alignTransform.js +356 -0
  4. package/src/defaultTagOrder.js +168 -0
  5. package/src/exportParser.js +957 -0
  6. package/src/getDefaultTagStructureForMode.js +969 -0
  7. package/src/index.js +266 -0
  8. package/src/iterateJsdoc.js +2555 -0
  9. package/src/jsdocUtils.js +1693 -0
  10. package/src/rules/checkAccess.js +45 -0
  11. package/src/rules/checkAlignment.js +63 -0
  12. package/src/rules/checkExamples.js +594 -0
  13. package/src/rules/checkIndentation.js +75 -0
  14. package/src/rules/checkLineAlignment.js +364 -0
  15. package/src/rules/checkParamNames.js +404 -0
  16. package/src/rules/checkPropertyNames.js +152 -0
  17. package/src/rules/checkSyntax.js +30 -0
  18. package/src/rules/checkTagNames.js +314 -0
  19. package/src/rules/checkTypes.js +535 -0
  20. package/src/rules/checkValues.js +220 -0
  21. package/src/rules/emptyTags.js +88 -0
  22. package/src/rules/implementsOnClasses.js +64 -0
  23. package/src/rules/importsAsDependencies.js +131 -0
  24. package/src/rules/informativeDocs.js +182 -0
  25. package/src/rules/matchDescription.js +286 -0
  26. package/src/rules/matchName.js +147 -0
  27. package/src/rules/multilineBlocks.js +333 -0
  28. package/src/rules/noBadBlocks.js +109 -0
  29. package/src/rules/noBlankBlockDescriptions.js +69 -0
  30. package/src/rules/noBlankBlocks.js +53 -0
  31. package/src/rules/noDefaults.js +85 -0
  32. package/src/rules/noMissingSyntax.js +195 -0
  33. package/src/rules/noMultiAsterisks.js +134 -0
  34. package/src/rules/noRestrictedSyntax.js +91 -0
  35. package/src/rules/noTypes.js +73 -0
  36. package/src/rules/noUndefinedTypes.js +328 -0
  37. package/src/rules/requireAsteriskPrefix.js +189 -0
  38. package/src/rules/requireDescription.js +161 -0
  39. package/src/rules/requireDescriptionCompleteSentence.js +333 -0
  40. package/src/rules/requireExample.js +118 -0
  41. package/src/rules/requireFileOverview.js +154 -0
  42. package/src/rules/requireHyphenBeforeParamDescription.js +178 -0
  43. package/src/rules/requireJsdoc.js +629 -0
  44. package/src/rules/requireParam.js +592 -0
  45. package/src/rules/requireParamDescription.js +89 -0
  46. package/src/rules/requireParamName.js +55 -0
  47. package/src/rules/requireParamType.js +89 -0
  48. package/src/rules/requireProperty.js +48 -0
  49. package/src/rules/requirePropertyDescription.js +25 -0
  50. package/src/rules/requirePropertyName.js +25 -0
  51. package/src/rules/requirePropertyType.js +25 -0
  52. package/src/rules/requireReturns.js +238 -0
  53. package/src/rules/requireReturnsCheck.js +141 -0
  54. package/src/rules/requireReturnsDescription.js +59 -0
  55. package/src/rules/requireReturnsType.js +51 -0
  56. package/src/rules/requireThrows.js +111 -0
  57. package/src/rules/requireYields.js +216 -0
  58. package/src/rules/requireYieldsCheck.js +208 -0
  59. package/src/rules/sortTags.js +557 -0
  60. package/src/rules/tagLines.js +359 -0
  61. package/src/rules/textEscaping.js +146 -0
  62. package/src/rules/validTypes.js +368 -0
  63. package/src/tagNames.js +234 -0
  64. package/src/utils/hasReturnValue.js +549 -0
@@ -0,0 +1,195 @@
1
+ import iterateJsdoc from '../iterateJsdoc.js';
2
+
3
+ /**
4
+ * @typedef {{
5
+ * comment: string,
6
+ * context: string,
7
+ * message: string,
8
+ * minimum: import('../iterateJsdoc.js').Integer
9
+ * }} ContextObject
10
+ */
11
+
12
+ /**
13
+ * @typedef {string|ContextObject} Context
14
+ */
15
+
16
+ /**
17
+ * @param {import('../iterateJsdoc.js').StateObject} state
18
+ * @returns {void}
19
+ */
20
+ const setDefaults = (state) => {
21
+ if (!state.selectorMap) {
22
+ state.selectorMap = {};
23
+ }
24
+ };
25
+
26
+ /**
27
+ * @param {import('../iterateJsdoc.js').StateObject} state
28
+ * @param {string} selector
29
+ * @param {string} comment
30
+ * @returns {void}
31
+ */
32
+ const incrementSelector = (state, selector, comment) => {
33
+ if (!state.selectorMap[selector]) {
34
+ state.selectorMap[selector] = {};
35
+ }
36
+
37
+ if (!state.selectorMap[selector][comment]) {
38
+ state.selectorMap[selector][comment] = 0;
39
+ }
40
+
41
+ state.selectorMap[selector][comment]++;
42
+ };
43
+
44
+ export default iterateJsdoc(({
45
+ context,
46
+ info: {
47
+ comment,
48
+ },
49
+ state,
50
+ utils,
51
+ }) => {
52
+ if (!context.options[0]) {
53
+ // Handle error later
54
+ return;
55
+ }
56
+
57
+ /**
58
+ * @type {Context[]}
59
+ */
60
+ const contexts = context.options[0].contexts;
61
+
62
+ const {
63
+ contextStr,
64
+ } = utils.findContext(contexts, comment);
65
+
66
+ setDefaults(state);
67
+
68
+ incrementSelector(state, contextStr, String(comment));
69
+ }, {
70
+ contextSelected: true,
71
+ exit ({
72
+ context,
73
+ settings,
74
+ state,
75
+ }) {
76
+ if (!context.options.length && !settings.contexts) {
77
+ context.report({
78
+ loc: {
79
+ end: {
80
+ column: 1,
81
+ line: 1,
82
+ },
83
+ start: {
84
+ column: 1,
85
+ line: 1,
86
+ },
87
+ },
88
+ message: 'Rule `no-missing-syntax` is missing a `contexts` option.',
89
+ });
90
+
91
+ return;
92
+ }
93
+
94
+ setDefaults(state);
95
+
96
+ /**
97
+ * @type {Context[]}
98
+ */
99
+ const contexts = (context.options[0] ?? {}).contexts ?? settings?.contexts;
100
+
101
+ // Report when MISSING
102
+ contexts.some((cntxt) => {
103
+ const contextStr = typeof cntxt === 'object' ? cntxt.context ?? 'any' : cntxt;
104
+ const comment = typeof cntxt === 'string' ? '' : cntxt?.comment;
105
+
106
+ const contextKey = contextStr === 'any' ? 'undefined' : contextStr;
107
+
108
+ if (
109
+ (!state.selectorMap[contextKey] ||
110
+ !state.selectorMap[contextKey][comment] ||
111
+ state.selectorMap[contextKey][comment] < (
112
+ // @ts-expect-error comment would need an object, not string
113
+ cntxt?.minimum ?? 1
114
+ )) &&
115
+ (contextStr !== 'any' || Object.values(state.selectorMap).every((cmmnt) => {
116
+ return !cmmnt[comment] || cmmnt[comment] < (
117
+ // @ts-expect-error comment would need an object, not string
118
+ cntxt?.minimum ?? 1
119
+ );
120
+ }))
121
+ ) {
122
+ const message = typeof cntxt === 'string' ?
123
+ 'Syntax is required: {{context}}' :
124
+ cntxt?.message ?? ('Syntax is required: {{context}}' +
125
+ (comment ? ' with {{comment}}' : ''));
126
+ context.report({
127
+ data: {
128
+ comment,
129
+ context: contextStr,
130
+ },
131
+ loc: {
132
+ end: {
133
+ column: 1,
134
+ line: 1,
135
+ },
136
+ start: {
137
+ column: 1,
138
+ line: 1,
139
+ },
140
+ },
141
+ message,
142
+ });
143
+
144
+ return true;
145
+ }
146
+
147
+ return false;
148
+ });
149
+ },
150
+ matchContext: true,
151
+ meta: {
152
+ docs: {
153
+ description: 'Reports when certain comment structures are always expected.',
154
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-missing-syntax.md#repos-sticky-header',
155
+ },
156
+ fixable: 'code',
157
+ schema: [
158
+ {
159
+ additionalProperties: false,
160
+ properties: {
161
+ contexts: {
162
+ items: {
163
+ anyOf: [
164
+ {
165
+ type: 'string',
166
+ },
167
+ {
168
+ additionalProperties: false,
169
+ properties: {
170
+ comment: {
171
+ type: 'string',
172
+ },
173
+ context: {
174
+ type: 'string',
175
+ },
176
+ message: {
177
+ type: 'string',
178
+ },
179
+ minimum: {
180
+ type: 'integer',
181
+ },
182
+ },
183
+ type: 'object',
184
+ },
185
+ ],
186
+ },
187
+ type: 'array',
188
+ },
189
+ },
190
+ type: 'object',
191
+ },
192
+ ],
193
+ type: 'suggestion',
194
+ },
195
+ });
@@ -0,0 +1,134 @@
1
+ import iterateJsdoc from '../iterateJsdoc.js';
2
+
3
+ const middleAsterisksBlockWS = /^([\t ]|\*(?!\*))+/u;
4
+ const middleAsterisksNoBlockWS = /^\*+/u;
5
+
6
+ const endAsterisksSingleLineBlockWS = /\*((?:\*|(?: |\t))*)\*$/u;
7
+ const endAsterisksMultipleLineBlockWS = /((?:\*|(?: |\t))*)\*$/u;
8
+
9
+ const endAsterisksSingleLineNoBlockWS = /\*(\**)\*$/u;
10
+ const endAsterisksMultipleLineNoBlockWS = /(\**)\*$/u;
11
+
12
+ export default iterateJsdoc(({
13
+ context,
14
+ jsdoc,
15
+ utils,
16
+ }) => {
17
+ const {
18
+ allowWhitespace = false,
19
+ preventAtEnd = true,
20
+ preventAtMiddleLines = true,
21
+ } = context.options[0] || {};
22
+
23
+ const middleAsterisks = allowWhitespace ? middleAsterisksNoBlockWS : middleAsterisksBlockWS;
24
+
25
+ // eslint-disable-next-line complexity -- Todo
26
+ jsdoc.source.some(({
27
+ tokens,
28
+ number,
29
+ }) => {
30
+ const {
31
+ delimiter,
32
+ tag,
33
+ name,
34
+ type,
35
+ description,
36
+ end,
37
+ postDelimiter,
38
+ } = tokens;
39
+
40
+ if (
41
+ preventAtMiddleLines &&
42
+ !end && !tag && !type && !name &&
43
+ (
44
+ !allowWhitespace && middleAsterisks.test(description) ||
45
+ allowWhitespace && middleAsterisks.test(postDelimiter + description)
46
+ )
47
+ ) {
48
+ // console.log('description', JSON.stringify(description));
49
+ const fix = () => {
50
+ tokens.description = description.replace(middleAsterisks, '');
51
+ };
52
+
53
+ utils.reportJSDoc(
54
+ 'Should be no multiple asterisks on middle lines.',
55
+ {
56
+ line: number,
57
+ },
58
+ fix,
59
+ true,
60
+ );
61
+
62
+ return true;
63
+ }
64
+
65
+ if (!preventAtEnd || !end) {
66
+ return false;
67
+ }
68
+
69
+ const isSingleLineBlock = delimiter === '/**';
70
+ const delim = isSingleLineBlock ? '*' : delimiter;
71
+ const endAsterisks = allowWhitespace ?
72
+ (isSingleLineBlock ? endAsterisksSingleLineNoBlockWS : endAsterisksMultipleLineNoBlockWS) :
73
+ (isSingleLineBlock ? endAsterisksSingleLineBlockWS : endAsterisksMultipleLineBlockWS);
74
+
75
+ const endingAsterisksAndSpaces = (
76
+ allowWhitespace ? postDelimiter + description + delim : description + delim
77
+ ).match(
78
+ endAsterisks,
79
+ );
80
+
81
+ if (
82
+ !endingAsterisksAndSpaces ||
83
+ !isSingleLineBlock && endingAsterisksAndSpaces[1] && !endingAsterisksAndSpaces[1].trim()
84
+ ) {
85
+ return false;
86
+ }
87
+
88
+ const endFix = () => {
89
+ if (!isSingleLineBlock) {
90
+ tokens.delimiter = '';
91
+ }
92
+
93
+ tokens.description = (description + delim).replace(endAsterisks, '');
94
+ };
95
+
96
+ utils.reportJSDoc(
97
+ 'Should be no multiple asterisks on end lines.',
98
+ {
99
+ line: number,
100
+ },
101
+ endFix,
102
+ true,
103
+ );
104
+
105
+ return true;
106
+ });
107
+ }, {
108
+ iterateAllJsdocs: true,
109
+ meta: {
110
+ docs: {
111
+ description: '',
112
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-multi-asterisks.md#repos-sticky-header',
113
+ },
114
+ fixable: 'code',
115
+ schema: [
116
+ {
117
+ additionalProperties: false,
118
+ properties: {
119
+ allowWhitespace: {
120
+ type: 'boolean',
121
+ },
122
+ preventAtEnd: {
123
+ type: 'boolean',
124
+ },
125
+ preventAtMiddleLines: {
126
+ type: 'boolean',
127
+ },
128
+ },
129
+ type: 'object',
130
+ },
131
+ ],
132
+ type: 'suggestion',
133
+ },
134
+ });
@@ -0,0 +1,91 @@
1
+ import iterateJsdoc from '../iterateJsdoc.js';
2
+
3
+ export default iterateJsdoc(({
4
+ context,
5
+ info: {
6
+ comment,
7
+ },
8
+ report,
9
+ utils,
10
+ }) => {
11
+ if (!context.options.length) {
12
+ report('Rule `no-restricted-syntax` is missing a `contexts` option.');
13
+
14
+ return;
15
+ }
16
+
17
+ const {
18
+ contexts,
19
+ } = context.options[0];
20
+
21
+ const {
22
+ foundContext,
23
+ contextStr,
24
+ } = utils.findContext(contexts, comment);
25
+
26
+ // We are not on the *particular* matching context/comment, so don't assume
27
+ // we need reporting
28
+ if (!foundContext) {
29
+ return;
30
+ }
31
+
32
+ const message = /** @type {import('../iterateJsdoc.js').ContextObject} */ (
33
+ foundContext
34
+ )?.message ??
35
+ 'Syntax is restricted: {{context}}' +
36
+ (comment ? ' with {{comment}}' : '');
37
+
38
+ report(message, null, null, comment ? {
39
+ comment,
40
+ context: contextStr,
41
+ } : {
42
+ context: contextStr,
43
+ });
44
+ }, {
45
+ contextSelected: true,
46
+ meta: {
47
+ docs: {
48
+ description: 'Reports when certain comment structures are present.',
49
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-restricted-syntax.md#repos-sticky-header',
50
+ },
51
+ fixable: 'code',
52
+ schema: [
53
+ {
54
+ additionalProperties: false,
55
+ properties: {
56
+ contexts: {
57
+ items: {
58
+ anyOf: [
59
+ {
60
+ type: 'string',
61
+ },
62
+ {
63
+ additionalProperties: false,
64
+ properties: {
65
+ comment: {
66
+ type: 'string',
67
+ },
68
+ context: {
69
+ type: 'string',
70
+ },
71
+ message: {
72
+ type: 'string',
73
+ },
74
+ },
75
+ type: 'object',
76
+ },
77
+ ],
78
+ },
79
+ type: 'array',
80
+ },
81
+ },
82
+ required: [
83
+ 'contexts',
84
+ ],
85
+ type: 'object',
86
+ },
87
+ ],
88
+ type: 'suggestion',
89
+ },
90
+ nonGlobalSettings: true,
91
+ });
@@ -0,0 +1,73 @@
1
+ import iterateJsdoc from '../iterateJsdoc.js';
2
+
3
+ /**
4
+ * @param {import('comment-parser').Line} line
5
+ */
6
+ const removeType = ({
7
+ tokens,
8
+ }) => {
9
+ tokens.postTag = '';
10
+ tokens.type = '';
11
+ };
12
+
13
+ export default iterateJsdoc(({
14
+ utils,
15
+ }) => {
16
+ if (!utils.isIteratingFunction() && !utils.isVirtualFunction()) {
17
+ return;
18
+ }
19
+
20
+ const tags = utils.getPresentTags([
21
+ 'param', 'arg', 'argument', 'returns', 'return',
22
+ ]);
23
+
24
+ for (const tag of tags) {
25
+ if (tag.type) {
26
+ utils.reportJSDoc(`Types are not permitted on @${tag.tag}.`, tag, () => {
27
+ for (const source of tag.source) {
28
+ removeType(source);
29
+ }
30
+ });
31
+ }
32
+ }
33
+ }, {
34
+ contextDefaults: true,
35
+ meta: {
36
+ docs: {
37
+ description: 'This rule reports types being used on `@param` or `@returns`.',
38
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-types.md#repos-sticky-header',
39
+ },
40
+ fixable: 'code',
41
+ schema: [
42
+ {
43
+ additionalProperties: false,
44
+ properties: {
45
+ contexts: {
46
+ items: {
47
+ anyOf: [
48
+ {
49
+ type: 'string',
50
+ },
51
+ {
52
+ additionalProperties: false,
53
+ properties: {
54
+ comment: {
55
+ type: 'string',
56
+ },
57
+ context: {
58
+ type: 'string',
59
+ },
60
+ },
61
+ type: 'object',
62
+ },
63
+ ],
64
+ },
65
+ type: 'array',
66
+ },
67
+ },
68
+ type: 'object',
69
+ },
70
+ ],
71
+ type: 'suggestion',
72
+ },
73
+ });