diff --git a/.README/rules/check-param-names.md b/.README/rules/check-param-names.md index dcea0efa..7cb8b829 100644 --- a/.README/rules/check-param-names.md +++ b/.README/rules/check-param-names.md @@ -81,12 +81,16 @@ item at the same level is destructured as destructuring will prevent other access and this option is only intended to permit documenting extra properties that are available and actually used in the function. +### `disableMissingParamChecks` + +Whether to avoid checks for missing `@param` definitions. Defaults to `false`. Change to `true` if you want to be able to omit properties. + ## Context and settings ||| |---|---| |Context|`ArrowFunctionExpression`, `FunctionDeclaration`, `FunctionExpression`| -|Options|`allowExtraTrailingParamDocs`, `checkDestructured`, `checkRestProperty`, `checkTypesPattern`, `disableExtraPropertyReporting`, `enableFixer`, `useDefaultObjectProperties`| +|Options|`allowExtraTrailingParamDocs`, `checkDestructured`, `checkRestProperty`, `checkTypesPattern`, `disableExtraPropertyReporting`, `disableMissingParamChecks`, `enableFixer`, `useDefaultObjectProperties`| |Tags|`param`| |Aliases|`arg`, `argument`| |Recommended|true| diff --git a/docs/rules/check-param-names.md b/docs/rules/check-param-names.md index cca4fbd4..9182f8ba 100644 --- a/docs/rules/check-param-names.md +++ b/docs/rules/check-param-names.md @@ -116,6 +116,12 @@ item at the same level is destructured as destructuring will prevent other access and this option is only intended to permit documenting extra properties that are available and actually used in the function. + + +### disableMissingParamChecks + +Whether to check for missing `@param` definitions. Defaults to `false`. Change to `true` if you want to be able to omit properties. + ## Context and settings @@ -123,7 +129,7 @@ that are available and actually used in the function. ||| |---|---| |Context|`ArrowFunctionExpression`, `FunctionDeclaration`, `FunctionExpression`| -|Options|`allowExtraTrailingParamDocs`, `checkDestructured`, `checkRestProperty`, `checkTypesPattern`, `disableExtraPropertyReporting`, `enableFixer`, `useDefaultObjectProperties`| +|Options|`allowExtraTrailingParamDocs`, `checkDestructured`, `checkRestProperty`, `checkTypesPattern`, `disableExtraPropertyReporting`, `disableMissingParamChecks`, `enableFixer`, `useDefaultObjectProperties`| |Tags|`param`| |Aliases|`arg`, `argument`| |Recommended|true| diff --git a/src/rules/checkParamNames.js b/src/rules/checkParamNames.js index 7837c6e6..3569efcd 100644 --- a/src/rules/checkParamNames.js +++ b/src/rules/checkParamNames.js @@ -7,6 +7,7 @@ import iterateJsdoc from '../iterateJsdoc.js'; * @param {boolean} checkRestProperty * @param {RegExp} checkTypesRegex * @param {boolean} disableExtraPropertyReporting + * @param {boolean} disableMissingParamChecks * @param {boolean} enableFixer * @param {import('../jsdocUtils.js').ParamNameInfo[]} functionParameterNames * @param {import('comment-parser').Block} jsdoc @@ -21,6 +22,7 @@ const validateParameterNames = ( checkRestProperty, checkTypesRegex, disableExtraPropertyReporting, + disableMissingParamChecks, enableFixer, functionParameterNames, jsdoc, utils, report, ) => { @@ -245,10 +247,20 @@ const validateParameterNames = ( return item; }).filter((item) => { return item !== 'this'; - }).join(', '); + }); + + // When disableMissingParamChecks is true tag names can be omitted. + // Report when the tag names do not match the expected names or they are used out of order. + if (disableMissingParamChecks) { + const usedExpectedNames = expectedNames.map(a => a?.toString()).filter(expectedName => expectedName && actualNames.includes(expectedName)); + const usedInOrder = actualNames.every((actualName, idx) => actualName === usedExpectedNames[idx]); + if (usedInOrder) { + return false; + } + } report( - `Expected @${targetTagName} names to be "${expectedNames}". Got "${actualNames.join(', ')}".`, + `Expected @${targetTagName} names to be "${expectedNames.join(', ')}". Got "${actualNames.join(', ')}".`, null, tag, ); @@ -329,6 +341,7 @@ export default iterateJsdoc(({ enableFixer = false, useDefaultObjectProperties = false, disableExtraPropertyReporting = false, + disableMissingParamChecks = false, } = context.options[0] || {}; const checkTypesRegex = utils.getRegexFromString(checkTypesPattern); @@ -349,6 +362,7 @@ export default iterateJsdoc(({ checkRestProperty, checkTypesRegex, disableExtraPropertyReporting, + disableMissingParamChecks, enableFixer, functionParameterNames, jsdoc, @@ -389,6 +403,9 @@ export default iterateJsdoc(({ disableExtraPropertyReporting: { type: 'boolean', }, + disableMissingParamChecks: { + type: 'boolean', + }, enableFixer: { type: 'boolean', }, diff --git a/test/rules/assertions/checkParamNames.js b/test/rules/assertions/checkParamNames.js index a666ff87..0148603d 100644 --- a/test/rules/assertions/checkParamNames.js +++ b/test/rules/assertions/checkParamNames.js @@ -1183,6 +1183,89 @@ export default { parser: typescriptEslintParser }, }, + { + code: ` + /** + * @param foo + * @param foo.bar + */ + function quux (bar, foo) { + } + `, + options: [ + { + disableMissingParamChecks: false, + }, + ], + errors: [ + { + line: 3, + message: 'Expected @param names to be "bar, foo". Got "foo".', + }, + ], + }, + { + code: ` + /** + * @param foo + */ + function quux (bar, baz) { + } + `, + options: [ + { + disableMissingParamChecks: true, + }, + ], + errors: [ + { + line: 3, + message: 'Expected @param names to be "bar, baz". Got "foo".', + }, + ], + }, + { + code: ` + /** + * @param bar + * @param foo + */ + function quux (foo, bar) { + } + `, + options: [ + { + disableMissingParamChecks: true, + }, + ], + errors: [ + { + line: 3, + message: 'Expected @param names to be "foo, bar". Got "bar, foo".', + }, + ], + }, + { + code: ` + /** + * @param foo + * @param bar + */ + function quux (foo) { + } + `, + options: [ + { + disableMissingParamChecks: true, + }, + ], + errors: [ + { + line: 4, + message: '@param "bar" does not match an existing function parameter.', + }, + ], + }, ], valid: [ { @@ -1835,5 +1918,48 @@ export default { parser: typescriptEslintParser }, }, + { + code: ` + /** + * Documentation + */ + function quux (foo, bar) { + } + `, + options: [ + { + disableMissingParamChecks: true, + }, + ], + }, + { + code: ` + /** + * @param bar + * @param bar.baz + */ + function quux (foo, bar) { + } + `, + options: [ + { + disableMissingParamChecks: true, + }, + ], + }, + { + code: ` + /** + * @param foo + */ + function quux (foo, bar) { + } + `, + options: [ + { + disableMissingParamChecks: true, + }, + ], + }, ], };