Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 37 additions & 27 deletions src/rules/requireParam.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import _ from 'lodash';
import iterateJsdoc from '../iterateJsdoc';

type T = [string, () => T];
Expand Down Expand Up @@ -47,11 +48,14 @@ export default iterateJsdoc(({
}

const {
autoIncrementBase = 0,
checkRestProperty = false,
checkDestructured = true,
checkTypesPattern = '/^(?:[oO]bject|[aA]rray|PlainObject|Generic(?:Object|Array))$/',
enableFixer = true,
enableRootFixer = true,
checkRestProperty = false,
enableRestElementFixer = true,
checkTypesPattern = '/^(?:[oO]bject|[aA]rray|PlainObject|Generic(?:Object|Array))$/',
unnamedRootBase = ['root'],
} = context.options[0] || {};

const lastSlashPos = checkTypesPattern.lastIndexOf('/');
Expand Down Expand Up @@ -93,10 +97,6 @@ export default iterateJsdoc(({
return paramTags.length;
};

const {
autoIncrementBase = 0,
unnamedRootBase = ['root'],
} = context.options[0] || {};
let [nextRootName, incremented, namer] = rootNamer([...unnamedRootBase], autoIncrementBase);

functionParameterNames.forEach((functionParameterName, functionParameterIdx) => {
Expand Down Expand Up @@ -125,32 +125,39 @@ export default iterateJsdoc(({
}

names.forEach((paramName, idx) => {
if (jsdocParameterNames && !jsdocParameterNames.find(({name}) => {
// Add root if the root name is not in the docs (and is not already
// in the tags to be fixed)
if (!jsdocParameterNames.find(({name}) => {
return name === rootName;
}) && !missingTags.find(({functionParameterName: fpn}) => {
return fpn === rootName;
})) {
if (!missingTags.find(({functionParameterName: fpn}) => {
return fpn === rootName;
})) {
const emptyParamIdx = jsdocParameterNames.findIndex(({name}) => {
return !name;
});
const emptyParamIdx = jsdocParameterNames.findIndex(({name}) => {
return !name;
});

if (emptyParamIdx > -1) {
missingTags.push({
functionParameterIdx: emptyParamIdx,
functionParameterName: rootName,
inc,
remove: true,
});
} else {
missingTags.push({
functionParameterIdx: paramIndex[rootName],
functionParameterName: rootName,
inc,
});
}
if (emptyParamIdx > -1) {
missingTags.push({
functionParameterIdx: emptyParamIdx,
functionParameterName: rootName,
inc,
remove: true,
});
} else {
missingTags.push({
functionParameterIdx: _.has(paramIndex, rootName) ?
paramIndex[rootName] :
paramIndex[paramName],
functionParameterName: rootName,
inc,
});
}
}

if (!checkDestructured) {
return;
}

if (!checkRestProperty && rests[idx]) {
return;
}
Expand Down Expand Up @@ -252,6 +259,9 @@ export default iterateJsdoc(({
default: true,
type: 'boolean',
},
checkDestructured: {
type: 'boolean',
},
checkGetters: {
default: false,
type: 'boolean',
Expand Down
50 changes: 50 additions & 0 deletions test/rules/assertions/requireParam.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,39 @@ export default {
}
`,
},
{
code: `
/**
* @param foo
*/
function quux (foo, bar, {baz}) {

}
`,
errors: [
{
message: 'Missing JSDoc @param "bar" declaration.',
},
{
message: 'Missing JSDoc @param "root0" declaration.',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This message is confusing, what is root0?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is part of the feature added in #498 --that when a destructured parameter is also missing its root declaration, that by default, the word "root" will be used followed by a 0-based auto-incrementing number for each subsequent root (one can avoid the numeric additions with specific config, or add additional items to an options array so that until all the items in the array are exhausted, it will cycle through the names, e.g., ["root", "cfg", "config"] will add @param root then @param cfg, then @config0, with the last item auto-incrementing). You could see our discussion about it in the PR for more background.

Copy link
Collaborator Author

@brettz9 brettz9 May 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though I think it makes sense to use root0 in the fixes, subject to user configuration (disablable by setting enableRootFixer to false), we could give a message like "Missing JSDoc @param destructuring root object declaration". Does that sound better? And I'd be personally ok having enableRootFixer default to false, but sometimes I think it is good when the defaults are--within reason and not genuinely harmful--a little on the aggressive side since it informs users of the features they might not learn about otherwise, and if they don't want it, they can come looking for how to disable.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param declaration for destructured parameter {bar}.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That could potentially become quite long though, no? e.g., {bar, baz, foo: {def: {ghi}}, many, others}

Copy link
Collaborator Author

@brettz9 brettz9 May 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we could just slice it to a certain maximum length, adding ellipses as needed, and the curly bracket always at the end.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How should we differentiate in this test case though?

      code: `
          /**
           *
           */
          function quux ({foo}) {

          }
      `,
      errors: [
        {
          message: 'Missing JSDoc @param "root0" declaration.',
        },
        {
          message: 'Missing JSDoc @param "root0.foo" declaration.',
        },
      ],
      output: `
          /**
           * @param root0
           * @param root0.foo
           */
          function quux ({foo}) {

          }
      `,

Report Missing JSDoc @param "{foo}" declaration twice?

Copy link
Collaborator Author

@brettz9 brettz9 May 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to report just once because the root object may or may not already be defined, and if not defined, there should continue to be a separate message and fix.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, if it's ok, can we discuss this as a separate issue for fixing reporting messages? This discussion, though valid, is concerning a preexisting behavior (we refer to root0 in other messages, not just in this PR). It would be nice to get this merged so the disabling functionality is available sooner.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as the solution, I guess I can just change it to report:

Missing JSDoc @param "{foo}" declaration
Missing JSDoc @param "foo" in "{foo}" declaration

},
],
options: [
{
checkDestructured: false,
},
],
output: `
/**
* @param foo
* @param bar
* @param root0
*/
function quux (foo, bar, {baz}) {

}
`,
},
{
code: `
/**
Expand Down Expand Up @@ -2696,5 +2729,22 @@ export default {
`,
parser: require.resolve('@typescript-eslint/parser'),
},
{
code: `
/**
* @param foo
* @param bar
* @param cfg
*/
function quux (foo, bar, {baz}) {

}
`,
options: [
{
checkDestructured: false,
},
],
},
],
};