Skip to content

Commit

Permalink
feat(match-description): ensure @desc checked by default; check m…
Browse files Browse the repository at this point in the history
…ore desc-like tags by default; check non-empty tags; #233
  • Loading branch information
brettz9 committed Jun 25, 2023
1 parent 3a5dd7d commit 1b9d9e4
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 78 deletions.
27 changes: 24 additions & 3 deletions .README/rules/match-description.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ by our supported Node versions):

``^\n?([A-Z`\\d_][\\s\\S]*[.?!`]\\s*)?$``

Applies to the jsdoc block description and `@description` (or `@desc`)
by default but the `tags` option (see below) may be used to match other tags.
Applies by default to the jsdoc block description and to the following tags:

- `@description`/`@desc`
- `@summary`
- `@file`/`@fileoverview`/`@overview`
- `@classdesc`

In addition, the `tags` option (see below) may be used to match other tags.

The default (and all regex options) defaults to using (only) the `u` flag, so
to add your own flags, encapsulate your expression as a string, but like a
Expand Down Expand Up @@ -54,6 +60,21 @@ You may provide a custom default message by using the following format:
This can be overridden per tag or for the main block description by setting
`message` within `tags` or `mainDescription`, respectively.

### `nonemptyTags`

If not set to `false`, will enforce that the following tags have at least
some content:

- `@copyright`
- `@example`
- `@see`
- `@todo`
- `@throws`/`@exception`
- `@yields`/`@yield`

If you supply your own tag description for any of the above tags in `tags`,
your description will take precedence.

### `tags`

If you want different regular expressions to apply to tags, you may use
Expand Down Expand Up @@ -161,7 +182,7 @@ section of our README for more on the expected format.
|Aliases|`@desc`|
|Recommended|false|
|Settings||
|Options|`contexts`, `mainDescription`, `matchDescription`, `message`, `tags`|
|Options|`contexts`, `mainDescription`, `matchDescription`, `message`, `nonemptyTags`, `tags`|

## Failing examples

Expand Down
53 changes: 42 additions & 11 deletions docs/rules/match-description.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* [Options](#user-content-match-description-options)
* [`matchDescription`](#user-content-match-description-options-matchdescription)
* [`message`](#user-content-match-description-options-message)
* [`nonemptyTags`](#user-content-match-description-options-nonemptytags)
* [`tags`](#user-content-match-description-options-tags)
* [`mainDescription`](#user-content-match-description-options-maindescription)
* [`contexts`](#user-content-match-description-options-contexts)
Expand All @@ -21,8 +22,14 @@ by our supported Node versions):

``^\n?([A-Z`\\d_][\\s\\S]*[.?!`]\\s*)?$``

Applies to the jsdoc block description and `@description` (or `@desc`)
by default but the `tags` option (see below) may be used to match other tags.
Applies by default to the jsdoc block description and to the following tags:

- `@description`/`@desc`
- `@summary`
- `@file`/`@fileoverview`/`@overview`
- `@classdesc`

In addition, the `tags` option (see below) may be used to match other tags.

The default (and all regex options) defaults to using (only) the `u` flag, so
to add your own flags, encapsulate your expression as a string, but like a
Expand Down Expand Up @@ -71,6 +78,23 @@ You may provide a custom default message by using the following format:
This can be overridden per tag or for the main block description by setting
`message` within `tags` or `mainDescription`, respectively.

<a name="user-content-match-description-options-nonemptytags"></a>
<a name="match-description-options-nonemptytags"></a>
### <code>nonemptyTags</code>

If not set to `false`, will enforce that the following tags have at least
some content:

- `@copyright`
- `@example`
- `@see`
- `@todo`
- `@throws`/`@exception`
- `@yields`/`@yield`

If you supply your own tag description for any of the above tags in `tags`,
your description will take precedence.

<a name="user-content-match-description-options-tags"></a>
<a name="match-description-options-tags"></a>
### <code>tags</code>
Expand Down Expand Up @@ -186,7 +210,7 @@ section of our README for more on the expected format.
|Aliases|`@desc`|
|Recommended|false|
|Settings||
|Options|`contexts`, `mainDescription`, `matchDescription`, `message`, `tags`|
|Options|`contexts`, `mainDescription`, `matchDescription`, `message`, `nonemptyTags`, `tags`|

<a name="user-content-match-description-failing-examples"></a>
<a name="match-description-failing-examples"></a>
Expand Down Expand Up @@ -335,7 +359,6 @@ function quux (foo) {
function quux () {

}
// "jsdoc/match-description": ["error"|"warn", {"tags":{"summary":true}}]
// Message: JSDoc description does not satisfy the regex pattern.

/**
Expand Down Expand Up @@ -368,7 +391,6 @@ function quux () {
function quux (foo) {

}
// "jsdoc/match-description": ["error"|"warn", {"tags":{"description":true}}]
// Message: JSDoc description does not satisfy the regex pattern.

/**
Expand Down Expand Up @@ -602,6 +624,13 @@ function quux () {
function foo(): string;
// "jsdoc/match-description": ["error"|"warn", {"contexts":[{"comment":"JsdocBlock[endLine=0]"}],"matchDescription":"^\\S[\\s\\S]*\\S$"}]
// Message: JSDoc description does not satisfy the regex pattern.

/**
* @copyright
*/
function quux () {
}
// Message: JSDoc description must not be empty.
````


Expand Down Expand Up @@ -722,7 +751,6 @@ function quux () {
function quux () {

}
// "jsdoc/match-description": ["error"|"warn", {"tags":{"description":true}}]

/**
* @description Foo
Expand All @@ -732,13 +760,11 @@ function quux () {
function quux () {

}
// "jsdoc/match-description": ["error"|"warn", {"tags":{"description":true}}]

/** @description Foo bar. */
function quux () {

}
// "jsdoc/match-description": ["error"|"warn", {"tags":{"description":true}}]

/**
* @description Foo
Expand All @@ -747,7 +773,6 @@ function quux () {
function quux () {

}
// "jsdoc/match-description": ["error"|"warn", {"tags":{"description":true}}]

/**
* Foo. {@see Math.sin}.
Expand Down Expand Up @@ -872,7 +897,7 @@ const q = {
// "jsdoc/match-description": ["error"|"warn", {"contexts":[]}]

/**
* @description foo.
* @deprecated foo.
*/
function quux () {

Expand All @@ -887,7 +912,6 @@ function quux () {
function quux () {

}
// "jsdoc/match-description": ["error"|"warn", {"tags":{"summary":true}}]

/**
* Foo.
Expand Down Expand Up @@ -975,5 +999,12 @@ function foo(): string;
*/
function foo(): void;
// "jsdoc/match-description": ["error"|"warn", {"contexts":[{"comment":"JsdocBlock[endLine!=0]:not(:has(JsdocTag))"}],"matchDescription":"^\\S[\\s\\S]*\\S$"}]

/**
* @copyright
*/
function quux () {
}
// "jsdoc/match-description": ["error"|"warn", {"nonemptyTags":false}]
````

2 changes: 1 addition & 1 deletion src/iterateJsdoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -1644,7 +1644,7 @@ const getUtils = (

/** @type {GetTagsByType} */
utils.getTagsByType = (tags) => {
return jsdocUtils.getTagsByType(context, mode, tags, tagNamePreference);
return jsdocUtils.getTagsByType(context, mode, tags);
};

/** @type {HasOptionTag} */
Expand Down
6 changes: 2 additions & 4 deletions src/jsdocUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -1422,14 +1422,12 @@ const tagsWithNamesAndDescriptions = new Set([
* @param {import('eslint').Rule.RuleContext} context
* @param {ParserMode|undefined} mode
* @param {import('comment-parser').Spec[]} tags
* @param {TagNamePreference} tagPreference
* @returns {{
* tagsWithNames: import('comment-parser').Spec[],
* tagsWithoutNames: import('comment-parser').Spec[]
* }}
*/
const getTagsByType = (context, mode, tags, tagPreference) => {
const descName = getPreferredTagName(context, mode, 'description', tagPreference);
const getTagsByType = (context, mode, tags) => {
/**
* @type {import('comment-parser').Spec[]}
*/
Expand All @@ -1439,7 +1437,7 @@ const getTagsByType = (context, mode, tags, tagPreference) => {
tag: tagName,
} = tag;
const tagWithName = tagsWithNamesAndDescriptions.has(tagName);
if (!tagWithName && tagName !== descName) {
if (!tagWithName) {
tagsWithoutNames.push(tag);
}

Expand Down
60 changes: 51 additions & 9 deletions src/rules/matchDescription.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ export default iterateJsdoc(({
mainDescription,
matchDescription,
message,
tags,
nonemptyTags = true,
tags = {},
} = context.options[0] || {};

/**
Expand Down Expand Up @@ -81,7 +82,52 @@ export default iterateJsdoc(({
validateDescription(description);
}

if (!tags || !Object.keys(tags).length) {
/**
* @param {string} tagName
* @returns {boolean}
*/
const hasNoTag = (tagName) => {
return !tags[tagName];
};

for (const tag of [
'description',
'summary',
'file',
'classdesc',
]) {
utils.forEachPreferredTag(tag, (matchingJsdocTag, targetTagName) => {
const desc = (matchingJsdocTag.name + ' ' + utils.getTagDescription(matchingJsdocTag)).trim();
if (hasNoTag(targetTagName)) {
validateDescription(desc, matchingJsdocTag);
}
}, true);
}

if (nonemptyTags) {
for (const tag of [
'copyright',
'example',
'see',
'throws',
'todo',
'yields',
]) {
utils.forEachPreferredTag(tag, (matchingJsdocTag, targetTagName) => {
const desc = (matchingJsdocTag.name + ' ' + utils.getTagDescription(matchingJsdocTag)).trim();

if (hasNoTag(targetTagName) && !(/.+/u).test(desc)) {
report(
'JSDoc description must not be empty.',
null,
matchingJsdocTag,
);
}
});
}
}

if (!Object.keys(tags).length) {
return;
}

Expand All @@ -93,13 +139,6 @@ export default iterateJsdoc(({
return Boolean(tags[tagName]);
};

utils.forEachPreferredTag('description', (matchingJsdocTag, targetTagName) => {
const desc = (matchingJsdocTag.name + ' ' + utils.getTagDescription(matchingJsdocTag)).trim();
if (hasOptionTag(targetTagName)) {
validateDescription(desc, matchingJsdocTag);
}
}, true);

const whitelistedTags = utils.filterTags(({
tag: tagName,
}) => {
Expand Down Expand Up @@ -195,6 +234,9 @@ export default iterateJsdoc(({
message: {
type: 'string',
},
nonemptyTags: {
type: 'boolean',
},
tags: {
patternProperties: {
'.*': {
Expand Down
Loading

0 comments on commit 1b9d9e4

Please sign in to comment.