Skip to content

Commit

Permalink
feat(check-param-names): add option allowExtraTrailingParamDocs t…
Browse files Browse the repository at this point in the history
…o avoid reporting additional `@param`'s beyond actual function's arguments; fixes #450
  • Loading branch information
brettz9 committed Dec 27, 2019
1 parent 423f95c commit 4532e66
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 33 deletions.
10 changes: 10 additions & 0 deletions .README/rules/check-param-names.md
Expand Up @@ -2,9 +2,19 @@

Ensures that parameter names in JSDoc match those in the function declaration.

#### Options

##### `allowExtraTrailingParamDocs`

If set to `true`, this option will allow extra `@param` definitions (e.g.,
representing future expected or virtual params) to be present without needing
their presence within the function signature. Other inconsistencies between
`@param`'s and present function parameters will still be reported.

|||
|---|---|
|Context|`ArrowFunctionExpression`, `FunctionDeclaration`, `FunctionExpression`|
|Options|`allowExtraTrailingParamDocs`|
|Tags|`param`|

<!-- assertions checkParamNames -->
Expand Down
77 changes: 49 additions & 28 deletions README.md
Expand Up @@ -1403,9 +1403,21 @@ function quux () {

Ensures that parameter names in JSDoc match those in the function declaration.

<a name="eslint-plugin-jsdoc-rules-check-param-names-options-3"></a>
#### Options

<a name="eslint-plugin-jsdoc-rules-check-param-names-options-3-allowextratrailingparamdocs"></a>
##### <code>allowExtraTrailingParamDocs</code>

If set to `true`, this option will allow extra `@param` definitions (e.g.,
representing future expected or virtual params) to be present without needing
their presence within the function signature. Other inconsistencies between
`@param`'s and present function parameters will still be reported.

|||
|---|---|
|Context|`ArrowFunctionExpression`, `FunctionDeclaration`, `FunctionExpression`|
|Options|`allowExtraTrailingParamDocs`|
|Tags|`param`|

The following patterns are considered problems:
Expand Down Expand Up @@ -1618,6 +1630,15 @@ export class SomeClass {
*/
function quux (error, code = 1) {
};

/**
* @param foo
* @param bar
*/
function quux (foo) {

}
// Options: [{"allowExtraTrailingParamDocs":true}]
````


Expand Down Expand Up @@ -1840,10 +1861,10 @@ wizaction

Note that the tags indicated as replacements in `settings.jsdoc.tagNamePreference` will automatically be considered as valid.

<a name="eslint-plugin-jsdoc-rules-check-tag-names-options-3"></a>
<a name="eslint-plugin-jsdoc-rules-check-tag-names-options-4"></a>
#### Options

<a name="eslint-plugin-jsdoc-rules-check-tag-names-options-3-definedtags"></a>
<a name="eslint-plugin-jsdoc-rules-check-tag-names-options-4-definedtags"></a>
##### <code>definedTags</code>

Use an array of `definedTags` strings to configure additional, allowed tags.
Expand Down Expand Up @@ -2443,7 +2464,7 @@ Date
RegExp
```

<a name="eslint-plugin-jsdoc-rules-check-types-options-4"></a>
<a name="eslint-plugin-jsdoc-rules-check-types-options-5"></a>
#### Options

`check-types` allows one option:
Expand Down Expand Up @@ -3281,22 +3302,22 @@ This rule checks the values for a handful of tags:
`allowedAuthors` is present, ensure that the author value is one
of these array items.

<a name="eslint-plugin-jsdoc-rules-check-values-options-5"></a>
<a name="eslint-plugin-jsdoc-rules-check-values-options-6"></a>
#### Options

<a name="eslint-plugin-jsdoc-rules-check-values-options-5-allowedauthors"></a>
<a name="eslint-plugin-jsdoc-rules-check-values-options-6-allowedauthors"></a>
##### <code>allowedAuthors</code>

An array of allowable author values. If absent, only non-whitespace will
be checked for.

<a name="eslint-plugin-jsdoc-rules-check-values-options-5-allowedlicenses"></a>
<a name="eslint-plugin-jsdoc-rules-check-values-options-6-allowedlicenses"></a>
##### <code>allowedLicenses</code>

An array of allowable license values or `true` to allow any license text.
If present as an array, will be used in place of SPDX identifiers.

<a name="eslint-plugin-jsdoc-rules-check-values-options-5-licensepattern"></a>
<a name="eslint-plugin-jsdoc-rules-check-values-options-6-licensepattern"></a>
##### <code>licensePattern</code>

A string to be converted into a `RegExp` (with `u` flag) and whose first
Expand Down Expand Up @@ -3525,10 +3546,10 @@ is set to "closure" (which allows types).
- `@public`
- `@static`
<a name="eslint-plugin-jsdoc-rules-empty-tags-options-6"></a>
<a name="eslint-plugin-jsdoc-rules-empty-tags-options-7"></a>
#### Options
<a name="eslint-plugin-jsdoc-rules-empty-tags-options-6-tags"></a>
<a name="eslint-plugin-jsdoc-rules-empty-tags-options-7-tags"></a>
##### <code>tags</code>
If you want additional tags to be checked for their descriptions, you may
Expand Down Expand Up @@ -3743,10 +3764,10 @@ by our supported Node versions):
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.
<a name="eslint-plugin-jsdoc-rules-match-description-options-7"></a>
<a name="eslint-plugin-jsdoc-rules-match-description-options-8"></a>
#### Options
<a name="eslint-plugin-jsdoc-rules-match-description-options-7-matchdescription"></a>
<a name="eslint-plugin-jsdoc-rules-match-description-options-8-matchdescription"></a>
##### <code>matchDescription</code>
You can supply your own expression to override the default, passing a
Expand All @@ -3761,7 +3782,7 @@ You can supply your own expression to override the default, passing a
As with the default, the supplied regular expression will be applied with the
Unicode (`"u"`) flag and is *not* case-insensitive.
<a name="eslint-plugin-jsdoc-rules-match-description-options-7-tags-1"></a>
<a name="eslint-plugin-jsdoc-rules-match-description-options-8-tags-1"></a>
##### <code>tags</code>
If you want different regular expressions to apply to tags, you may use
Expand Down Expand Up @@ -3798,7 +3819,7 @@ its "description" (e.g., for `@returns {someType} some description`, the
description is `some description` while for `@some-tag xyz`, the description
is `xyz`).
<a name="eslint-plugin-jsdoc-rules-match-description-options-7-maindescription"></a>
<a name="eslint-plugin-jsdoc-rules-match-description-options-8-maindescription"></a>
##### <code>mainDescription</code>
If you wish to override the main function description without changing the
Expand All @@ -3820,7 +3841,7 @@ 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`.
<a name="eslint-plugin-jsdoc-rules-match-description-options-7-contexts"></a>
<a name="eslint-plugin-jsdoc-rules-match-description-options-8-contexts"></a>
##### <code>contexts</code>
Set this to an array of strings representing the AST context
Expand Down Expand Up @@ -4440,7 +4461,7 @@ function quux () {
Enforces a consistent padding of the block description.
<a name="eslint-plugin-jsdoc-rules-newline-after-description-options-8"></a>
<a name="eslint-plugin-jsdoc-rules-newline-after-description-options-9"></a>
#### Options
This rule allows one optional string argument. If it is `"always"` then a problem is raised when there is no newline after the description. If it is `"never"` then a problem is raised when there is a newline after the description. The default value is `"always"`.
Expand Down Expand Up @@ -4711,7 +4732,7 @@ The following types are always considered defined.
Note that preferred types indicated within `settings.jsdoc.preferredTypes` will
also be assumed to be defined.
<a name="eslint-plugin-jsdoc-rules-no-undefined-types-options-9"></a>
<a name="eslint-plugin-jsdoc-rules-no-undefined-types-options-10"></a>
#### Options
An option object may have the following key:
Expand Down Expand Up @@ -5137,10 +5158,10 @@ tag descriptions are written in complete sentences, i.e.,
* A colon or semi-colon followed by two line breaks is still part of the
containing paragraph (unlike normal dual line breaks).
<a name="eslint-plugin-jsdoc-rules-require-description-complete-sentence-options-10"></a>
<a name="eslint-plugin-jsdoc-rules-require-description-complete-sentence-options-11"></a>
#### Options
<a name="eslint-plugin-jsdoc-rules-require-description-complete-sentence-options-10-tags-2"></a>
<a name="eslint-plugin-jsdoc-rules-require-description-complete-sentence-options-11-tags-2"></a>
##### <code>tags</code>
If you want additional tags to be checked for their descriptions, you may
Expand Down Expand Up @@ -5628,7 +5649,7 @@ Requires that all functions have a description.
`"tag"`) must have a non-empty description that explains the purpose of the
method.
<a name="eslint-plugin-jsdoc-rules-require-description-options-11"></a>
<a name="eslint-plugin-jsdoc-rules-require-description-options-12"></a>
#### Options
An options object may have any of the following properties:
Expand Down Expand Up @@ -5913,25 +5934,25 @@ Requires that all functions have examples.
* All functions must have one or more `@example` tags.
* Every example tag must have a non-empty description that explains the method's usage.
<a name="eslint-plugin-jsdoc-rules-require-example-options-12"></a>
<a name="eslint-plugin-jsdoc-rules-require-example-options-13"></a>
#### Options
This rule has an object option.
<a name="eslint-plugin-jsdoc-rules-require-example-options-12-exemptedby"></a>
<a name="eslint-plugin-jsdoc-rules-require-example-options-13-exemptedby"></a>
##### <code>exemptedBy</code>
Array of tags (e.g., `['type']`) whose presence on the document
block avoids the need for an `@example`. Defaults to an empty array.
<a name="eslint-plugin-jsdoc-rules-require-example-options-12-avoidexampleonconstructors"></a>
<a name="eslint-plugin-jsdoc-rules-require-example-options-13-avoidexampleonconstructors"></a>
##### <code>avoidExampleOnConstructors</code>
Set to `true` to avoid the need for an example on a constructor (whether
indicated as such by a jsdoc tag or by being within an ES6 `class`).
Defaults to `false`.
<a name="eslint-plugin-jsdoc-rules-require-example-options-12-contexts-1"></a>
<a name="eslint-plugin-jsdoc-rules-require-example-options-13-contexts-1"></a>
##### <code>contexts</code>
Set this to an array of strings representing the AST context
Expand Down Expand Up @@ -6109,7 +6130,7 @@ function quux () {
Requires a hyphen before the `@param` description.
<a name="eslint-plugin-jsdoc-rules-require-hyphen-before-param-description-options-13"></a>
<a name="eslint-plugin-jsdoc-rules-require-hyphen-before-param-description-options-14"></a>
#### Options
This rule takes one optional string argument. If it is `"always"` then a problem is raised when there is no hyphen before the description. If it is `"never"` then a problem is raised when there is a hyphen before the description. The default value is `"always"`.
Expand Down Expand Up @@ -6215,7 +6236,7 @@ function quux () {
Checks for presence of jsdoc comments, on class declarations as well as
functions.
<a name="eslint-plugin-jsdoc-rules-require-jsdoc-options-14"></a>
<a name="eslint-plugin-jsdoc-rules-require-jsdoc-options-15"></a>
#### Options
Accepts one optional options object with the following optional keys.
Expand Down Expand Up @@ -7403,7 +7424,7 @@ function quux (foo) {
Requires that all function parameters are documented.
<a name="eslint-plugin-jsdoc-rules-require-param-options-15"></a>
<a name="eslint-plugin-jsdoc-rules-require-param-options-16"></a>
#### Options
An options object accepts one optional property:
Expand Down Expand Up @@ -8503,7 +8524,7 @@ Requires returns are documented.
Will also report if multiple `@returns` tags are present.
<a name="eslint-plugin-jsdoc-rules-require-returns-options-16"></a>
<a name="eslint-plugin-jsdoc-rules-require-returns-options-17"></a>
#### Options
- `exemptedBy` - Array of tags (e.g., `['type']`) whose presence on the document
Expand Down Expand Up @@ -9005,7 +9026,7 @@ Also impacts behaviors on namepath (or event)-defining and pointing tags:
allow `#`, `.`, or `~` at the end (which is not allowed at the end of
normal paths).
<a name="eslint-plugin-jsdoc-rules-valid-types-options-17"></a>
<a name="eslint-plugin-jsdoc-rules-valid-types-options-18"></a>
#### Options
- `allowEmptyNamepaths` (default: true) - Set to `false` to disallow
Expand Down
40 changes: 35 additions & 5 deletions src/rules/checkParamNames.js
@@ -1,7 +1,10 @@
import entries from 'object.entries-ponyfill';
import iterateJsdoc from '../iterateJsdoc';

const validateParameterNames = (targetTagName : string, functionParameterNames : Array<string>, jsdoc, jsdocNode, utils, report) => {
const validateParameterNames = (
targetTagName : string, allowExtraTrailingParamDocs: boolean,
functionParameterNames : Array<string>, jsdoc, jsdocNode, utils, report,
) => {
if (!jsdoc || !jsdoc.tags) {
return false;
}
Expand All @@ -27,6 +30,10 @@ const validateParameterNames = (targetTagName : string, functionParameterNames :
const functionParameterName = functionParameterNames[index];

if (!functionParameterName) {
if (allowExtraTrailingParamDocs) {
return false;
}

report(
`@${targetTagName} "${tag.name}" does not match an existing function parameter.`,
null,
Expand Down Expand Up @@ -59,7 +66,10 @@ const validateParameterNames = (targetTagName : string, functionParameterNames :
});
};

const validateParameterNamesDeep = (targetTagName : string, jsdocParameterNames : Array<string>, jsdoc, report : Function) => {
const validateParameterNamesDeep = (
targetTagName : string, allowExtraTrailingParamDocs: boolean,
jsdocParameterNames : Array<string>, jsdoc, report : Function,
) => {
let lastRealParameter;

return jsdocParameterNames.some((jsdocParameterName, idx) => {
Expand Down Expand Up @@ -97,27 +107,47 @@ const validateParameterNamesDeep = (targetTagName : string, jsdocParameterNames
};

export default iterateJsdoc(({
context,
jsdoc,
jsdocNode,
report,
utils,
}) => {
const functionParameterNames = utils.getFunctionParameterNames();
const {allowExtraTrailingParamDocs} = context.options[0] || {};

const jsdocParameterNamesDeep = utils.getJsdocParameterNamesDeep();
if (!jsdocParameterNamesDeep) {
return;
}
const functionParameterNames = utils.getFunctionParameterNames();
const targetTagName = utils.getPreferredTagName({tagName: 'param'});
const isError = validateParameterNames(targetTagName, functionParameterNames, jsdoc, jsdocNode, utils, report);
const isError = validateParameterNames(
targetTagName, allowExtraTrailingParamDocs, functionParameterNames,
jsdoc, jsdocNode, utils, report,
);

if (isError) {
return;
}

validateParameterNamesDeep(targetTagName, jsdocParameterNamesDeep, jsdoc, report);
validateParameterNamesDeep(
targetTagName, allowExtraTrailingParamDocs, jsdocParameterNamesDeep,
jsdoc, report,
);
}, {
meta: {
fixable: 'code',
schema: [
{
additionalProperties: false,
properties: {
allowExtraTrailingParamDocs: {
type: 'boolean',
},
},
type: 'object',
},
],
type: 'suggestion',
},
});
16 changes: 16 additions & 0 deletions test/rules/assertions/checkParamNames.js
Expand Up @@ -380,5 +380,21 @@ export default {
};
`,
},
{
code: `
/**
* @param foo
* @param bar
*/
function quux (foo) {
}
`,
options: [
{
allowExtraTrailingParamDocs: true,
},
],
},
],
};

0 comments on commit 4532e66

Please sign in to comment.