Skip to content

Commit 6985244

Browse files
committed
feat(match-description): allow arbitrary tags; also fixes returns/return to avoid skipping matching of an initial "name" and space
1 parent eab2813 commit 6985244

File tree

4 files changed

+254
-6
lines changed

4 files changed

+254
-6
lines changed

.README/rules/match-description.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ tag should be linted with the `matchDescription` value (or the default).
5050
}
5151
```
5252

53+
The tags `@param`/`@arg`/`@argument` will be properly parsed to ensure that
54+
the "description" subject to matching refers to only the text after the name.
55+
All other tags will treat all text after the tag and space as being part of
56+
its "description".
57+
5358
##### `mainDescription`
5459

5560
If you wish to override the main function description without changing the
@@ -82,6 +87,6 @@ Overrides the default contexts (see below).
8287
|Context|`ArrowFunctionExpression`, `FunctionDeclaration`, `FunctionExpression`; others when `contexts` option enabled|
8388
|Tags|N/A by default but see `tags` options|
8489
|Settings||
85-
|Options|`contexts`, `tags` (allows for 'param', 'arg', 'argument', 'returns', 'return', 'description', 'desc'), `mainDescription`, `matchDescription`|
90+
|Options|`contexts`, `tags` (allows for 'param', 'arg', 'argument', 'description', 'desc', and any added to `tags` option, e.g., 'returns', 'return'), `mainDescription`, `matchDescription`|
8691

8792
<!-- assertions matchDescription -->

README.md

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2428,6 +2428,11 @@ tag should be linted with the `matchDescription` value (or the default).
24282428
}
24292429
```
24302430

2431+
The tags `@param`/`@arg`/`@argument` will be properly parsed to ensure that
2432+
the "description" subject to matching refers to only the text after the name.
2433+
All other tags will treat all text after the tag and space as being part of
2434+
its "description".
2435+
24312436
<a name="eslint-plugin-jsdoc-rules-match-description-options-3-maindescription"></a>
24322437
##### <code>mainDescription</code>
24332438

@@ -2462,7 +2467,7 @@ Overrides the default contexts (see below).
24622467
|Context|`ArrowFunctionExpression`, `FunctionDeclaration`, `FunctionExpression`; others when `contexts` option enabled|
24632468
|Tags|N/A by default but see `tags` options|
24642469
|Settings||
2465-
|Options|`contexts`, `tags` (allows for 'param', 'arg', 'argument', 'returns', 'return', 'description', 'desc'), `mainDescription`, `matchDescription`|
2470+
|Options|`contexts`, `tags` (allows for 'param', 'arg', 'argument', 'description', 'desc', and any added to `tags` option, e.g., 'returns', 'return'), `mainDescription`, `matchDescription`|
24662471

24672472
The following patterns are considered problems:
24682473

@@ -2538,6 +2543,39 @@ function quux (foo) {
25382543
// Options: [{"tags":{"param":true}}]
25392544
// Message: JSDoc description does not satisfy the regex pattern.
25402545

2546+
/**
2547+
* Foo.
2548+
*
2549+
* @summary foo.
2550+
*/
2551+
function quux () {
2552+
2553+
}
2554+
// Options: [{"tags":{"summary":true}}]
2555+
// Message: JSDoc description does not satisfy the regex pattern.
2556+
2557+
/**
2558+
* Foo.
2559+
*
2560+
* @author
2561+
*/
2562+
function quux () {
2563+
2564+
}
2565+
// Options: [{"tags":{"author":".+"}}]
2566+
// Message: JSDoc description does not satisfy the regex pattern.
2567+
2568+
/**
2569+
* Foo.
2570+
*
2571+
* @x-tag
2572+
*/
2573+
function quux () {
2574+
2575+
}
2576+
// Options: [{"tags":{"x-tag":".+"}}]
2577+
// Message: JSDoc description does not satisfy the regex pattern.
2578+
25412579
/**
25422580
* Foo.
25432581
*
@@ -2797,6 +2835,14 @@ function quux () {
27972835
}
27982836
// Options: [{"tags":{"returns":true}}]
27992837

2838+
/**
2839+
* @returns {type1} Foo bar.
2840+
*/
2841+
function quux () {
2842+
2843+
}
2844+
// Options: [{"tags":{"returns":true}}]
2845+
28002846
/**
28012847
* @description Foo bar.
28022848
*/
@@ -2934,6 +2980,36 @@ function quux () {
29342980

29352981
}
29362982
// Options: [{"tags":{"param":true}}]
2983+
2984+
/**
2985+
* Foo.
2986+
*
2987+
* @summary Foo.
2988+
*/
2989+
function quux () {
2990+
2991+
}
2992+
// Options: [{"tags":{"summary":true}}]
2993+
2994+
/**
2995+
* Foo.
2996+
*
2997+
* @author Somebody
2998+
*/
2999+
function quux () {
3000+
3001+
}
3002+
// Options: [{"tags":{"author":".+"}}]
3003+
3004+
/**
3005+
* Foo.
3006+
*
3007+
* @x-tag something
3008+
*/
3009+
function quux () {
3010+
3011+
}
3012+
// Options: [{"tags":{"x-tag":".+"}}]
29373013
````
29383014

29393015

src/rules/matchDescription.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import _ from 'lodash';
22
import iterateJsdoc from '../iterateJsdoc';
33

4-
const tagsWithDescriptions = ['param', 'arg', 'argument', 'returns', 'return'];
4+
const tagsWithNamesAndDescriptions = ['param', 'arg', 'argument'];
55

66
// If supporting Node >= 10, we could loosen the default to this for the
77
// initial letter: \\p{Upper}
@@ -57,22 +57,40 @@ export default iterateJsdoc(({
5757
return Boolean(options.tags[tagName]);
5858
};
5959

60+
let descName;
6061
utils.forEachPreferredTag('description', (matchingJsdocTag, targetTagName) => {
62+
descName = targetTagName;
6163
const description = (matchingJsdocTag.name + ' ' + matchingJsdocTag.description).trim();
6264
if (hasOptionTag(targetTagName)) {
6365
validateDescription(description, matchingJsdocTag);
6466
}
6567
});
6668

67-
const tags = utils.filterTags(({tag}) => {
68-
return tagsWithDescriptions.includes(tag) && hasOptionTag(tag);
69+
const tagsWithoutNames = [];
70+
const tagsWithNames = utils.filterTags((tag) => {
71+
const {tag: tagName} = tag;
72+
if (!hasOptionTag(tagName)) {
73+
return false;
74+
}
75+
const tagWithName = tagsWithNamesAndDescriptions.includes(tagName);
76+
if (!tagWithName && tagName !== descName) {
77+
tagsWithoutNames.push(tag);
78+
}
79+
80+
return tagWithName;
6981
});
7082

71-
tags.some((tag) => {
83+
tagsWithNames.some((tag) => {
7284
const description = _.trimStart(tag.description, '- ');
7385

7486
return validateDescription(description, tag);
7587
});
88+
89+
tagsWithoutNames.some((tag) => {
90+
const description = (tag.name + ' ' + tag.description).trim();
91+
92+
return validateDescription(description, tag);
93+
});
7694
}, {
7795
contextDefaults: true,
7896
meta: {

test/rules/assertions/matchDescription.js

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,81 @@ export default {
160160
}
161161
]
162162
},
163+
{
164+
code: `
165+
/**
166+
* Foo.
167+
*
168+
* @summary foo.
169+
*/
170+
function quux () {
171+
172+
}
173+
`,
174+
errors: [
175+
{
176+
line: 5,
177+
message: 'JSDoc description does not satisfy the regex pattern.'
178+
}
179+
],
180+
options: [
181+
{
182+
tags: {
183+
summary: true
184+
}
185+
}
186+
]
187+
},
188+
{
189+
code: `
190+
/**
191+
* Foo.
192+
*
193+
* @author
194+
*/
195+
function quux () {
196+
197+
}
198+
`,
199+
errors: [
200+
{
201+
line: 5,
202+
message: 'JSDoc description does not satisfy the regex pattern.'
203+
}
204+
],
205+
options: [
206+
{
207+
tags: {
208+
author: '.+'
209+
}
210+
}
211+
]
212+
},
213+
{
214+
code: `
215+
/**
216+
* Foo.
217+
*
218+
* @x-tag
219+
*/
220+
function quux () {
221+
222+
}
223+
`,
224+
errors: [
225+
{
226+
line: 5,
227+
message: 'JSDoc description does not satisfy the regex pattern.'
228+
}
229+
],
230+
options: [
231+
{
232+
tags: {
233+
'x-tag': '.+'
234+
}
235+
}
236+
]
237+
},
163238
{
164239
code: `
165240
/**
@@ -706,6 +781,23 @@ export default {
706781
}
707782
]
708783
},
784+
{
785+
code: `
786+
/**
787+
* @returns {type1} Foo bar.
788+
*/
789+
function quux () {
790+
791+
}
792+
`,
793+
options: [
794+
{
795+
tags: {
796+
returns: true
797+
}
798+
}
799+
]
800+
},
709801
{
710802
code: `
711803
/**
@@ -937,6 +1029,63 @@ export default {
9371029
param: true
9381030
}}
9391031
]
1032+
},
1033+
{
1034+
code: `
1035+
/**
1036+
* Foo.
1037+
*
1038+
* @summary Foo.
1039+
*/
1040+
function quux () {
1041+
1042+
}
1043+
`,
1044+
options: [
1045+
{
1046+
tags: {
1047+
summary: true
1048+
}
1049+
}
1050+
]
1051+
},
1052+
{
1053+
code: `
1054+
/**
1055+
* Foo.
1056+
*
1057+
* @author Somebody
1058+
*/
1059+
function quux () {
1060+
1061+
}
1062+
`,
1063+
options: [
1064+
{
1065+
tags: {
1066+
author: '.+'
1067+
}
1068+
}
1069+
]
1070+
},
1071+
{
1072+
code: `
1073+
/**
1074+
* Foo.
1075+
*
1076+
* @x-tag something
1077+
*/
1078+
function quux () {
1079+
1080+
}
1081+
`,
1082+
options: [
1083+
{
1084+
tags: {
1085+
'x-tag': '.+'
1086+
}
1087+
}
1088+
]
9401089
}
9411090
]
9421091
};

0 commit comments

Comments
 (0)