Skip to content

Commit

Permalink
feat(no-defaults): add new rule to reports defaults on @param or …
Browse files Browse the repository at this point in the history
…`@default` and optionally report optional args; fixes #477
  • Loading branch information
brettz9 committed Jan 11, 2020
1 parent 1383c02 commit d7fec9a
Show file tree
Hide file tree
Showing 6 changed files with 410 additions and 1 deletion.
42 changes: 42 additions & 0 deletions .README/rules/no-defaults.md
@@ -0,0 +1,42 @@
### `no-defaults`

This rule reports defaults being used on the relevant portion of `@param`
or `@default`. It also optionally reports the presence of the
square-bracketed optional arguments at all.

The rule is intended to prevent the indication of defaults on tags where
this would be redundant with ES6 default parameters (or for `@default`,
where it would be redundant with the context to which the `@default`
tag is attached).

Unless your `@default` is on a function, you will need to set `contexts`
to an appropriate context, including, if you wish, "any".

#### Options

##### `noOptionalParamNames`

Set this to `true` to report the presence of optional parameters. May be
used if the project is insisting on optionality being indicated by
the presence of ES6 default parameters (bearing in mind that such
"defaults" are only applied when the supplied value is missing or
`undefined` but not for `null` or other "falsey" values).

##### `contexts`

Set this to an array of strings representing the AST context
where you wish the rule to be applied.
Overrides the default contexts (see below). Set to `"any"` if you want
the rule to apply to any jsdoc block throughout your files (as is necessary
for finding function blocks not attached to a function declaration or
expression, i.e., `@callback` or `@function` (or its aliases `@func` or
`@method`) (including those associated with an `@interface`).

|||
|---|---|
|Context|`ArrowFunctionExpression`, `FunctionDeclaration`, `FunctionExpression`; others when `contexts` option enabled|
|Tags|`param`, `default`|
|Aliases|`arg`, `argument`, `defaultvalue`|
|Options|`contexts`, `noOptionalParamNames`|

<!-- assertions noDefaults -->
3 changes: 3 additions & 0 deletions src/index.js
Expand Up @@ -13,6 +13,7 @@ import emptyTags from './rules/emptyTags';
import implementsOnClasses from './rules/implementsOnClasses';
import matchDescription from './rules/matchDescription';
import newlineAfterDescription from './rules/newlineAfterDescription';
import noDefaults from './rules/noDefaults';
import noTypes from './rules/noTypes';
import noUndefinedTypes from './rules/noUndefinedTypes';
import requireDescriptionCompleteSentence from './rules/requireDescriptionCompleteSentence';
Expand Down Expand Up @@ -54,6 +55,7 @@ export default {
'jsdoc/implements-on-classes': 'warn',
'jsdoc/match-description': 'off',
'jsdoc/newline-after-description': 'warn',
'jsdoc/no-defaults': 'off',
'jsdoc/no-types': 'off',
'jsdoc/no-undefined-types': 'warn',
'jsdoc/require-description': 'off',
Expand Down Expand Up @@ -93,6 +95,7 @@ export default {
'implements-on-classes': implementsOnClasses,
'match-description': matchDescription,
'newline-after-description': newlineAfterDescription,
'no-defaults': noDefaults,
'no-types': noTypes,
'no-undefined-types': noUndefinedTypes,
'require-description': requireDescription,
Expand Down
11 changes: 10 additions & 1 deletion src/iterateJsdoc.js
Expand Up @@ -29,12 +29,21 @@ const parseComment = (commentNode, indent, trim = true) => {
// @see https://github.com/yavorskiy/comment-parser/issues/21
parsers: [
commentParser.PARSERS.parse_tag,
skipSeeLink(commentParser.PARSERS.parse_type),
skipSeeLink(
(str, data) => {
if (['default', 'defaultvalue'].includes(data.tag)) {
return null;
}

return commentParser.PARSERS.parse_type(str, data);
},
),
skipSeeLink(
(str, data) => {
if ([
'example', 'return', 'returns', 'throws', 'exception',
'access', 'version', 'since', 'license', 'author',
'default', 'defaultvalue',
].includes(data.tag)) {
return null;
}
Expand Down
52 changes: 52 additions & 0 deletions src/rules/noDefaults.js
@@ -0,0 +1,52 @@
import iterateJsdoc from '../iterateJsdoc';

export default iterateJsdoc(({
context,
utils,
}) => {
const {noOptionalParamNames} = context.options[0] || {};
const paramTags = utils.getPresentTags(['param', 'arg', 'argument']);
paramTags.forEach((tag) => {
if (noOptionalParamNames && tag.optional) {
utils.reportJSDoc(`Optional param names are not permitted on @${tag.tag}.`, tag, () => {
tag.default = '';
tag.optional = false;
});
} else if (tag.default) {
utils.reportJSDoc(`Defaults are not permitted on @${tag.tag}.`, tag, () => {
tag.default = '';
});
}
});
const defaultTags = utils.getPresentTags(['default', 'defaultvalue']);
defaultTags.forEach((tag) => {
if (tag.description) {
utils.reportJSDoc(`Default values are not permitted on @${tag.tag}.`, tag, () => {
tag.description = '';
});
}
});
}, {
contextDefaults: true,
meta: {
fixable: 'code',
schema: [
{
additionalProperties: false,
properties: {
contexts: {
items: {
type: 'string',
},
type: 'array',
},
noOptionalParamNames: {
type: 'boolean',
},
},
type: 'object',
},
],
type: 'suggestion',
},
});

0 comments on commit d7fec9a

Please sign in to comment.