Skip to content

Commit

Permalink
feat: message options for match-description; fixes #688
Browse files Browse the repository at this point in the history
  • Loading branch information
brettz9 committed Jun 21, 2021
1 parent 0bf7d82 commit 7257e44
Show file tree
Hide file tree
Showing 4 changed files with 338 additions and 19 deletions.
53 changes: 49 additions & 4 deletions .README/rules/match-description.md
Expand Up @@ -37,6 +37,21 @@ You can supply your own expression to override the default, passing a
}
```

##### `message`

You may provide a custom default message by using the following format:

```js
{
'jsdoc/match-description': ['error', {
message: 'The default dscription should begin with a capital letter.'
}]
}
```

This can be overridden per tag or for the main block description by setting
`message` within `tags` or `mainDescription`, respectively.

##### `tags`

If you want different regular expressions to apply to tags, you may use
Expand All @@ -63,6 +78,18 @@ tag should be linted with the `matchDescription` value (or the default).
}
```

Alternatively, you may supply an object with a `message` property to indicate
the error message for that tag.

```js
{
'jsdoc/match-description': ['error', {tags: {
param: {message: 'Begin with a hyphen', match: '\\- [A-Z].*\\.'},
returns: {message: 'Capitalize for returns (the default)', match: true}
}}]
}
```

The tags `@param`/`@arg`/`@argument` and `@property`/`@prop` will be properly
parsed to ensure that the matched "description" text includes only the text
after the name.
Expand All @@ -75,8 +102,9 @@ is `xyz`).

##### `mainDescription`

If you wish to override the main function description without changing the
default `match-description`, you may use `mainDescription`:
If you wish to override the main block description without changing the
default `match-description` (which can cascade to the `tags` with `true`),
you may use `mainDescription`:

```js
{
Expand All @@ -91,8 +119,25 @@ default `match-description`, you may use `mainDescription`:
```

There is no need to add `mainDescription: true`, as by default, the main
function (and only the main function) is linted, though you may disable
checking it by setting it to `false`.
block description (and only the main block description) is linted, though you
may disable checking it by setting it to `false`.

You may also provide an object with `message`:

```js
{
'jsdoc/match-description': ['error', {
mainDescription: {
message: 'Capitalize first word of JSDoc block descriptions',
match: '[A-Z].*\\.'
},
tags: {
param: true,
returns: true
}
}]
}
```

##### `contexts`

Expand Down
102 changes: 98 additions & 4 deletions README.md
Expand Up @@ -6390,6 +6390,22 @@ You can supply your own expression to override the default, passing a
}
```
<a name="eslint-plugin-jsdoc-rules-match-description-options-11-message"></a>
##### <code>message</code>
You may provide a custom default message by using the following format:
```js
{
'jsdoc/match-description': ['error', {
message: 'The default dscription should begin with a capital letter.'
}]
}
```
This can be overridden per tag or for the main block description by setting
`message` within `tags` or `mainDescription`, respectively.
<a name="eslint-plugin-jsdoc-rules-match-description-options-11-tags-2"></a>
##### <code>tags</code>
Expand Down Expand Up @@ -6417,6 +6433,18 @@ tag should be linted with the `matchDescription` value (or the default).
}
```
Alternatively, you may supply an object with a `message` property to indicate
the error message for that tag.
```js
{
'jsdoc/match-description': ['error', {tags: {
param: {message: 'Begin with a hyphen', match: '\\- [A-Z].*\\.'},
returns: {message: 'Capitalize for returns (the default)', match: true}
}}]
}
```
The tags `@param`/`@arg`/`@argument` and `@property`/`@prop` will be properly
parsed to ensure that the matched "description" text includes only the text
after the name.
Expand All @@ -6430,8 +6458,9 @@ is `xyz`).
<a name="eslint-plugin-jsdoc-rules-match-description-options-11-maindescription"></a>
##### <code>mainDescription</code>
If you wish to override the main function description without changing the
default `match-description`, you may use `mainDescription`:
If you wish to override the main block description without changing the
default `match-description` (which can cascade to the `tags` with `true`),
you may use `mainDescription`:
```js
{
Expand All @@ -6446,8 +6475,25 @@ default `match-description`, you may use `mainDescription`:
```
There is no need to add `mainDescription: true`, as by default, the main
function (and only the main function) is linted, though you may disable
checking it by setting it to `false`.
block description (and only the main block description) is linted, though you
may disable checking it by setting it to `false`.
You may also provide an object with `message`:
```js
{
'jsdoc/match-description': ['error', {
mainDescription: {
message: 'Capitalize first word of JSDoc block descriptions',
match: '[A-Z].*\\.'
},
tags: {
param: true,
returns: true
}
}]
}
```
<a name="eslint-plugin-jsdoc-rules-match-description-options-11-contexts-1"></a>
##### <code>contexts</code>
Expand Down Expand Up @@ -6482,6 +6528,15 @@ const q = class {
// "jsdoc/match-description": ["error"|"warn", {"contexts":["ClassExpression"]}]
// Message: JSDoc description does not satisfy the regex pattern.
/**
* foo.
*/
const q = class {
}
// "jsdoc/match-description": ["error"|"warn", {"contexts":["ClassExpression"],"message":"Needs to begin with a capital letter and end with an end mark."}]
// Message: Needs to begin with a capital letter and end with an end mark.
/**
* foo.
*/
Expand Down Expand Up @@ -6528,6 +6583,15 @@ function quux () {
// "jsdoc/match-description": ["error"|"warn", {"matchDescription":"-Я][А-я]+\\."}]
// Message: JSDoc description does not satisfy the regex pattern.
/**
* тест.
*/
function quux () {
}
// "jsdoc/match-description": ["error"|"warn", {"matchDescription":"-Я][А-я]+\\.","message":"Needs to begin with a capital letter and end with an end mark."}]
// Message: Needs to begin with a capital letter and end with an end mark.
/**
* Abc.
*/
Expand All @@ -6537,6 +6601,15 @@ function quux () {
// "jsdoc/match-description": ["error"|"warn", {"mainDescription":"-Я][А-я]+\\.","tags":{"param":true}}]
// Message: JSDoc description does not satisfy the regex pattern.
/**
* Abc.
*/
function quux () {
}
// "jsdoc/match-description": ["error"|"warn", {"mainDescription":{"match":"-Я][А-я]+\\.","message":"Needs to begin with a Cyrillic capital letter and end with a period."},"tags":{"param":true}}]
// Message: Needs to begin with a Cyrillic capital letter and end with a period.
/**
* Foo
*/
Expand Down Expand Up @@ -6640,6 +6713,17 @@ function quux (foo) {
*/
function quux (foo) {
}
// "jsdoc/match-description": ["error"|"warn", {"mainDescription":{"match":"^[a-zA-Z]*$","message":"Letters only"},"tags":{"param":{"match":true,"message":"Needs to begin with a capital letter and end with a period."}}}]
// Message: Needs to begin with a capital letter and end with a period.
/**
* Foo
*
* @param foo foo.
*/
function quux (foo) {
}
// "jsdoc/match-description": ["error"|"warn", {"mainDescription":false,"tags":{"param":true}}]
// Message: JSDoc description does not satisfy the regex pattern.
Expand Down Expand Up @@ -6858,6 +6942,16 @@ function quux () {
}
/**
* Foo.
*
* Bar.
*/
function quux () {
}
// "jsdoc/match-description": ["error"|"warn", {"message":"This won't be shown"}]
/**
* Тест.
*/
Expand Down
86 changes: 75 additions & 11 deletions src/rules/matchDescription.js
Expand Up @@ -16,28 +16,48 @@ export default iterateJsdoc(({
context,
utils,
}) => {
const options = context.options[0] || {};
const {
mainDescription,
matchDescription,
message,
tags,
} = context.options[0] || {};

const validateDescription = (description, tag) => {
if (!tag && options.mainDescription === false) {
let mainDescriptionMatch = mainDescription;
let errorMessage = message;
if (typeof mainDescription === 'object') {
mainDescriptionMatch = mainDescription.match;
errorMessage = mainDescription.message;
}
if (!tag && mainDescriptionMatch === false) {
return;
}

let tagValue = options.mainDescription;
let tagValue = mainDescriptionMatch;
if (tag) {
const tagName = tag.tag;
tagValue = options.tags[tagName];
if (typeof tags[tagName] === 'object') {
tagValue = tags[tagName].match;
errorMessage = tags[tagName].message;
} else {
tagValue = tags[tagName];
}
}

const regex = utils.getRegexFromString(
stringOrDefault(tagValue, options.matchDescription),
stringOrDefault(tagValue, matchDescription),
);

if (!regex.test(description)) {
report('JSDoc description does not satisfy the regex pattern.', null, tag || {
// Add one as description would typically be into block
line: jsdoc.source[0].number + 1,
});
report(
errorMessage || 'JSDoc description does not satisfy the regex pattern.',
null,
tag || {
// Add one as description would typically be into block
line: jsdoc.source[0].number + 1,
},
);
}
};

Expand All @@ -48,12 +68,12 @@ export default iterateJsdoc(({
);
}

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

const hasOptionTag = (tagName) => {
return Boolean(options.tags[tagName]);
return Boolean(tags[tagName]);
};

utils.forEachPreferredTag('description', (matchingJsdocTag, targetTagName) => {
Expand Down Expand Up @@ -121,12 +141,35 @@ export default iterateJsdoc(({
{
type: 'boolean',
},
{
additionalProperties: false,
properties: {
match: {
oneOf: [
{
format: 'regex',
type: 'string',
},
{
type: 'boolean',
},
],
},
message: {
type: 'string',
},
},
type: 'object',
},
],
},
matchDescription: {
format: 'regex',
type: 'string',
},
message: {
type: 'string',
},
tags: {
patternProperties: {
'.*': {
Expand All @@ -139,6 +182,27 @@ export default iterateJsdoc(({
enum: [true],
type: 'boolean',
},
{
additionalProperties: false,
properties: {
match: {
oneOf: [
{
format: 'regex',
type: 'string',
},
{
enum: [true],
type: 'boolean',
},
],
},
message: {
type: 'string',
},
},
type: 'object',
},
],
},
},
Expand Down

0 comments on commit 7257e44

Please sign in to comment.