Skip to content

Commit da1c85f

Browse files
committedOct 29, 2022
feat(require-param-type, require-param-description): add exemptDestructuredRootsFromChecks setting; fixes #752
Also: - feat(`require-param-type`): add `setDefaultDestructuredRootType` and `defaultDestructuredRootType` options - feat(`require-param-description`): add `setDefaultDestructuredRootDescription` and `defaultDestructuredRootDescription` options
1 parent 36f6f9c commit da1c85f

8 files changed

+511
-4
lines changed
 

‎.README/rules/require-param-description.md

+20-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,26 @@
22

33
Requires that each `@param` tag has a `description` value.
44

5+
Will exempt destructured roots and their children if
6+
`settings.exemptDestructuredRootsFromChecks` is set to `true` (e.g.,
7+
`@param {object} props` will be exempted from requiring a description given
8+
`function someFunc ({child1, child2})`).
9+
510
#### Options
611

12+
##### `setDefaultDestructuredRootDescription`
13+
14+
Whether to set a default destructured root description. For example, you may
15+
wish to avoid manually having to set the description for a `@param`
16+
corresponding to a destructured root object as it should always be the same
17+
type of object. Uses `defaultDestructuredRootDescription` for the description
18+
string. Defaults to `false`.
19+
20+
##### `defaultDestructuredRootDescription`
21+
22+
The description string to set by default for destructured roots. Defaults to
23+
"The root object".
24+
725
##### `contexts`
826

927
Set this to an array of strings representing the AST context (or an object with
@@ -23,6 +41,7 @@ section of our README for more on the expected format.
2341
|Tags|`param`|
2442
|Aliases|`arg`, `argument`|
2543
|Recommended|true|
26-
|Options|`contexts`|
44+
|Options|`setDefaultDestructuredRootDescription`, `defaultDestructuredRootDescription`, `contexts`|
45+
|Settings|`exemptDestructuredRootsFromChecks`|
2746

2847
<!-- assertions requireParamDescription -->

‎.README/rules/require-param-type.md

+19-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,25 @@
22

33
Requires that each `@param` tag has a `type` value.
44

5+
Will exempt destructured roots and their children if
6+
`settings.exemptDestructuredRootsFromChecks` is set to `true` (e.g.,
7+
`@param props` will be exempted from requiring a type given
8+
`function someFunc ({child1, child2})`).
9+
510
#### Options
611

12+
##### `setDefaultDestructuredRootType`
13+
14+
Whether to set a default destructured root type. For example, you may wish
15+
to avoid manually having to set the type for a `@param`
16+
corresponding to a destructured root object as it is always going to be an
17+
object. Uses `defaultDestructuredRootType` for the type string. Defaults to
18+
`false`.
19+
20+
##### `defaultDestructuredRootType`
21+
22+
The type string to set by default for destructured roots. Defaults to "object".
23+
724
##### `contexts`
825

926
Set this to an array of strings representing the AST context (or an object with
@@ -23,6 +40,7 @@ section of our README for more on the expected format.
2340
|Tags|`param`|
2441
|Aliases|`arg`, `argument`|
2542
|Recommended|true|
26-
|Options|`contexts`|
43+
|Options|`setDefaultDestructuredRootType`, `defaultDestructuredRootType`, `contexts`|
44+
|Settings|`exemptDestructuredRootsFromChecks`|
2745

2846
<!-- assertions requireParamType -->

‎README.md

+153-2
Original file line numberDiff line numberDiff line change
@@ -14772,10 +14772,32 @@ class A {
1477214772

1477314773
Requires that each `@param` tag has a `description` value.
1477414774

14775+
Will exempt destructured roots and their children if
14776+
`settings.exemptDestructuredRootsFromChecks` is set to `true` (e.g.,
14777+
`@param {object} props` will be exempted from requiring a description given
14778+
`function someFunc ({child1, child2})`).
14779+
1477514780
<a name="user-content-eslint-plugin-jsdoc-rules-require-param-description-options-29"></a>
1477614781
<a name="eslint-plugin-jsdoc-rules-require-param-description-options-29"></a>
1477714782
#### Options
1477814783

14784+
<a name="user-content-eslint-plugin-jsdoc-rules-require-param-description-options-29-setdefaultdestructuredrootdescription"></a>
14785+
<a name="eslint-plugin-jsdoc-rules-require-param-description-options-29-setdefaultdestructuredrootdescription"></a>
14786+
##### <code>setDefaultDestructuredRootDescription</code>
14787+
14788+
Whether to set a default destructured root description. For example, you may
14789+
wish to avoid manually having to set the description for a `@param`
14790+
corresponding to a destructured root object as it should always be the same
14791+
type of object. Uses `defaultDestructuredRootDescription` for the description
14792+
string. Defaults to `false`.
14793+
14794+
<a name="user-content-eslint-plugin-jsdoc-rules-require-param-description-options-29-defaultdestructuredrootdescription"></a>
14795+
<a name="eslint-plugin-jsdoc-rules-require-param-description-options-29-defaultdestructuredrootdescription"></a>
14796+
##### <code>defaultDestructuredRootDescription</code>
14797+
14798+
The description string to set by default for destructured roots. Defaults to
14799+
"The root object".
14800+
1477914801
<a name="user-content-eslint-plugin-jsdoc-rules-require-param-description-options-29-contexts-8"></a>
1478014802
<a name="eslint-plugin-jsdoc-rules-require-param-description-options-29-contexts-8"></a>
1478114803
##### <code>contexts</code>
@@ -14797,7 +14819,8 @@ section of our README for more on the expected format.
1479714819
|Tags|`param`|
1479814820
|Aliases|`arg`, `argument`|
1479914821
|Recommended|true|
14800-
|Options|`contexts`|
14822+
|Options|`setDefaultDestructuredRootDescription`, `defaultDestructuredRootDescription`, `contexts`|
14823+
|Settings|`exemptDestructuredRootsFromChecks`|
1480114824

1480214825
The following patterns are considered problems:
1480314826

@@ -14859,6 +14882,39 @@ function quux (foo) {
1485914882
}
1486014883
// "jsdoc/require-param-description": ["error"|"warn", {"contexts":[{"comment":"JsdocBlock:has(JsdocTag:not([name=props]))","context":"FunctionDeclaration"}]}]
1486114884
// Message: Missing JSDoc @param "foo" description.
14885+
14886+
/**
14887+
* @param {number} foo Foo description
14888+
* @param {object} root
14889+
* @param {boolean} baz Baz description
14890+
*/
14891+
function quux (foo, {bar}, baz) {
14892+
14893+
}
14894+
// "jsdoc/require-param-description": ["error"|"warn", {"setDefaultDestructuredRootDescription":true}]
14895+
// Message: Missing root description for @param.
14896+
14897+
/**
14898+
* @param {number} foo Foo description
14899+
* @param {object} root
14900+
* @param {boolean} baz Baz description
14901+
*/
14902+
function quux (foo, {bar}, baz) {
14903+
14904+
}
14905+
// "jsdoc/require-param-description": ["error"|"warn", {"defaultDestructuredRootDescription":"Root description","setDefaultDestructuredRootDescription":true}]
14906+
// Message: Missing root description for @param.
14907+
14908+
/**
14909+
* @param {number} foo Foo description
14910+
* @param {object} root
14911+
* @param {boolean} baz Baz description
14912+
*/
14913+
function quux (foo, {bar}, baz) {
14914+
14915+
}
14916+
// "jsdoc/require-param-description": ["error"|"warn", {"setDefaultDestructuredRootDescription":false}]
14917+
// Message: Missing JSDoc @param "root" description.
1486214918
````
1486314919

1486414920
The following patterns are not considered problems:
@@ -14903,6 +14959,26 @@ function quux (props) {
1490314959

1490414960
}
1490514961
// "jsdoc/require-param-description": ["error"|"warn", {"contexts":[{"comment":"JsdocBlock:has(JsdocTag:not([name=props]))","context":"FunctionDeclaration"}]}]
14962+
14963+
/**
14964+
* @param {number} foo Foo description
14965+
* @param {object} root
14966+
* @param {boolean} baz Baz description
14967+
*/
14968+
function quux (foo, {bar}, baz) {
14969+
14970+
}
14971+
// Settings: {"jsdoc":{"exemptDestructuredRootsFromChecks":true}}
14972+
14973+
/**
14974+
* @param {number} foo Foo description
14975+
* @param {object} root
14976+
* @param {object} root.bar
14977+
*/
14978+
function quux (foo, {bar: {baz}}) {
14979+
14980+
}
14981+
// Settings: {"jsdoc":{"exemptDestructuredRootsFromChecks":true}}
1490614982
````
1490714983

1490814984

@@ -15055,10 +15131,31 @@ function example(cb) {
1505515131

1505615132
Requires that each `@param` tag has a `type` value.
1505715133

15134+
Will exempt destructured roots and their children if
15135+
`settings.exemptDestructuredRootsFromChecks` is set to `true` (e.g.,
15136+
`@param props` will be exempted from requiring a type given
15137+
`function someFunc ({child1, child2})`).
15138+
1505815139
<a name="user-content-eslint-plugin-jsdoc-rules-require-param-type-options-31"></a>
1505915140
<a name="eslint-plugin-jsdoc-rules-require-param-type-options-31"></a>
1506015141
#### Options
1506115142

15143+
<a name="user-content-eslint-plugin-jsdoc-rules-require-param-type-options-31-setdefaultdestructuredroottype"></a>
15144+
<a name="eslint-plugin-jsdoc-rules-require-param-type-options-31-setdefaultdestructuredroottype"></a>
15145+
##### <code>setDefaultDestructuredRootType</code>
15146+
15147+
Whether to set a default destructured root type. For example, you may wish
15148+
to avoid manually having to set the type for a `@param`
15149+
corresponding to a destructured root object as it is always going to be an
15150+
object. Uses `defaultDestructuredRootType` for the type string. Defaults to
15151+
`false`.
15152+
15153+
<a name="user-content-eslint-plugin-jsdoc-rules-require-param-type-options-31-defaultdestructuredroottype"></a>
15154+
<a name="eslint-plugin-jsdoc-rules-require-param-type-options-31-defaultdestructuredroottype"></a>
15155+
##### <code>defaultDestructuredRootType</code>
15156+
15157+
The type string to set by default for destructured roots. Defaults to "object".
15158+
1506215159
<a name="user-content-eslint-plugin-jsdoc-rules-require-param-type-options-31-contexts-10"></a>
1506315160
<a name="eslint-plugin-jsdoc-rules-require-param-type-options-31-contexts-10"></a>
1506415161
##### <code>contexts</code>
@@ -15080,7 +15177,8 @@ section of our README for more on the expected format.
1508015177
|Tags|`param`|
1508115178
|Aliases|`arg`, `argument`|
1508215179
|Recommended|true|
15083-
|Options|`contexts`|
15180+
|Options|`setDefaultDestructuredRootType`, `defaultDestructuredRootType`, `contexts`|
15181+
|Settings|`exemptDestructuredRootsFromChecks`|
1508415182

1508515183
The following patterns are considered problems:
1508615184

@@ -15140,6 +15238,39 @@ function quux (foo) {
1514015238
}
1514115239
// Settings: {"jsdoc":{"tagNamePreference":{"param":false}}}
1514215240
// Message: Unexpected tag `@param`
15241+
15242+
/**
15243+
* @param {number} foo
15244+
* @param root
15245+
* @param {boolean} baz
15246+
*/
15247+
function quux (foo, {bar}, baz) {
15248+
15249+
}
15250+
// "jsdoc/require-param-type": ["error"|"warn", {"setDefaultDestructuredRootType":true}]
15251+
// Message: Missing root type for @param.
15252+
15253+
/**
15254+
* @param {number} foo
15255+
* @param root
15256+
* @param {boolean} baz
15257+
*/
15258+
function quux (foo, {bar}, baz) {
15259+
15260+
}
15261+
// "jsdoc/require-param-type": ["error"|"warn", {"defaultDestructuredRootType":"Object","setDefaultDestructuredRootType":true}]
15262+
// Message: Missing root type for @param.
15263+
15264+
/**
15265+
* @param {number} foo
15266+
* @param root
15267+
* @param {boolean} baz
15268+
*/
15269+
function quux (foo, {bar}, baz) {
15270+
15271+
}
15272+
// "jsdoc/require-param-type": ["error"|"warn", {"setDefaultDestructuredRootType":false}]
15273+
// Message: Missing JSDoc @param "root" type.
1514315274
````
1514415275

1514515276
The following patterns are not considered problems:
@@ -15176,6 +15307,26 @@ function quux (foo) {
1517615307
* @callback
1517715308
* @param foo
1517815309
*/
15310+
15311+
/**
15312+
* @param {number} foo
15313+
* @param root
15314+
* @param {boolean} baz
15315+
*/
15316+
function quux (foo, {bar}, baz) {
15317+
15318+
}
15319+
// Settings: {"jsdoc":{"exemptDestructuredRootsFromChecks":true}}
15320+
15321+
/**
15322+
* @param {number} foo
15323+
* @param root
15324+
* @param root.bar
15325+
*/
15326+
function quux (foo, {bar: {baz}}) {
15327+
15328+
}
15329+
// Settings: {"jsdoc":{"exemptDestructuredRootsFromChecks":true}}
1517915330
````
1518015331

1518115332

‎src/iterateJsdoc.js

+3
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,9 @@ const getSettings = (context) => {
818818
implementsReplacesDocs: context.settings.jsdoc?.implementsReplacesDocs,
819819
augmentsExtendsReplacesDocs: context.settings.jsdoc?.augmentsExtendsReplacesDocs,
820820

821+
// `require-param-type`, `require-param-description`
822+
exemptDestructuredRootsFromChecks: context.settings.jsdoc?.exemptDestructuredRootsFromChecks,
823+
821824
// Many rules, e.g., `check-tag-names`
822825
mode: context.settings.jsdoc?.mode ??
823826
(context.parserPath.includes('@typescript-eslint') ? 'typescript' : 'jsdoc'),

‎src/rules/requireParamDescription.js

+34
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,38 @@
11
import iterateJsdoc from '../iterateJsdoc';
22

33
export default iterateJsdoc(({
4+
context,
45
report,
6+
settings,
57
utils,
68
}) => {
9+
const {
10+
defaultDestructuredRootDescription = 'The root object',
11+
setDefaultDestructuredRootDescription = false,
12+
} = context.options[0] || {};
13+
14+
const functionParameterNames = utils.getFunctionParameterNames();
15+
16+
let rootCount = -1;
717
utils.forEachPreferredTag('param', (jsdocParameter, targetTagName) => {
18+
rootCount += jsdocParameter.name.includes('.') ? 0 : 1;
819
if (!jsdocParameter.description.trim()) {
20+
if (Array.isArray(functionParameterNames[rootCount])) {
21+
if (settings.exemptDestructuredRootsFromChecks) {
22+
return;
23+
}
24+
25+
if (setDefaultDestructuredRootDescription) {
26+
utils.reportJSDoc(`Missing root description for @${targetTagName}.`, jsdocParameter, () => {
27+
utils.changeTag(jsdocParameter, {
28+
description: defaultDestructuredRootDescription,
29+
postName: ' ',
30+
});
31+
});
32+
return;
33+
}
34+
}
35+
936
report(
1037
`Missing JSDoc @${targetTagName} "${jsdocParameter.name}" description.`,
1138
null,
@@ -20,6 +47,7 @@ export default iterateJsdoc(({
2047
description: 'Requires that each `@param` tag has a `description` value.',
2148
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-param-description',
2249
},
50+
fixable: 'code',
2351
schema: [
2452
{
2553
additionalProperties: false,
@@ -46,6 +74,12 @@ export default iterateJsdoc(({
4674
},
4775
type: 'array',
4876
},
77+
defaultDestructuredRootDescription: {
78+
type: 'string',
79+
},
80+
setDefaultDestructuredRootDescription: {
81+
type: 'boolean',
82+
},
4983
},
5084
type: 'object',
5185
},

‎src/rules/requireParamType.js

+34
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,38 @@
11
import iterateJsdoc from '../iterateJsdoc';
22

33
export default iterateJsdoc(({
4+
context,
45
report,
6+
settings,
57
utils,
68
}) => {
9+
const {
10+
defaultDestructuredRootType = 'object',
11+
setDefaultDestructuredRootType = false,
12+
} = context.options[0] || {};
13+
14+
const functionParameterNames = utils.getFunctionParameterNames();
15+
16+
let rootCount = -1;
717
utils.forEachPreferredTag('param', (jsdocParameter, targetTagName) => {
18+
rootCount += jsdocParameter.name.includes('.') ? 0 : 1;
819
if (!jsdocParameter.type) {
20+
if (Array.isArray(functionParameterNames[rootCount])) {
21+
if (settings.exemptDestructuredRootsFromChecks) {
22+
return;
23+
}
24+
25+
if (setDefaultDestructuredRootType) {
26+
utils.reportJSDoc(`Missing root type for @${targetTagName}.`, jsdocParameter, () => {
27+
utils.changeTag(jsdocParameter, {
28+
postType: ' ',
29+
type: `{${defaultDestructuredRootType}}`,
30+
});
31+
});
32+
return;
33+
}
34+
}
35+
936
report(
1037
`Missing JSDoc @${targetTagName} "${jsdocParameter.name}" type.`,
1138
null,
@@ -20,6 +47,7 @@ export default iterateJsdoc(({
2047
description: 'Requires that each `@param` tag has a `type` value.',
2148
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-param-type',
2249
},
50+
fixable: 'code',
2351
schema: [
2452
{
2553
additionalProperties: false,
@@ -46,6 +74,12 @@ export default iterateJsdoc(({
4674
},
4775
type: 'array',
4876
},
77+
defaultDestructuredRootType: {
78+
type: 'string',
79+
},
80+
setDefaultDestructuredRootType: {
81+
type: 'boolean',
82+
},
4983
},
5084
type: 'object',
5185
},

‎test/rules/assertions/requireParamDescription.js

+124
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,96 @@ export default {
153153
},
154154
],
155155
},
156+
{
157+
code: `
158+
/**
159+
* @param {number} foo Foo description
160+
* @param {object} root
161+
* @param {boolean} baz Baz description
162+
*/
163+
function quux (foo, {bar}, baz) {
164+
165+
}
166+
`,
167+
errors: [
168+
{
169+
line: 4,
170+
message: 'Missing root description for @param.',
171+
},
172+
],
173+
options: [
174+
{
175+
setDefaultDestructuredRootDescription: true,
176+
},
177+
],
178+
output: `
179+
/**
180+
* @param {number} foo Foo description
181+
* @param {object} root The root object
182+
* @param {boolean} baz Baz description
183+
*/
184+
function quux (foo, {bar}, baz) {
185+
186+
}
187+
`,
188+
},
189+
{
190+
code: `
191+
/**
192+
* @param {number} foo Foo description
193+
* @param {object} root
194+
* @param {boolean} baz Baz description
195+
*/
196+
function quux (foo, {bar}, baz) {
197+
198+
}
199+
`,
200+
errors: [
201+
{
202+
line: 4,
203+
message: 'Missing root description for @param.',
204+
},
205+
],
206+
options: [
207+
{
208+
defaultDestructuredRootDescription: 'Root description',
209+
setDefaultDestructuredRootDescription: true,
210+
},
211+
],
212+
output: `
213+
/**
214+
* @param {number} foo Foo description
215+
* @param {object} root Root description
216+
* @param {boolean} baz Baz description
217+
*/
218+
function quux (foo, {bar}, baz) {
219+
220+
}
221+
`,
222+
},
223+
{
224+
code: `
225+
/**
226+
* @param {number} foo Foo description
227+
* @param {object} root
228+
* @param {boolean} baz Baz description
229+
*/
230+
function quux (foo, {bar}, baz) {
231+
232+
}
233+
`,
234+
errors: [
235+
{
236+
line: 4,
237+
message: 'Missing JSDoc @param "root" description.',
238+
},
239+
],
240+
options: [
241+
{
242+
setDefaultDestructuredRootDescription: false,
243+
},
244+
],
245+
},
156246
],
157247
valid: [
158248
{
@@ -242,5 +332,39 @@ export default {
242332
},
243333
],
244334
},
335+
{
336+
code: `
337+
/**
338+
* @param {number} foo Foo description
339+
* @param {object} root
340+
* @param {boolean} baz Baz description
341+
*/
342+
function quux (foo, {bar}, baz) {
343+
344+
}
345+
`,
346+
settings: {
347+
jsdoc: {
348+
exemptDestructuredRootsFromChecks: true,
349+
},
350+
},
351+
},
352+
{
353+
code: `
354+
/**
355+
* @param {number} foo Foo description
356+
* @param {object} root
357+
* @param {object} root.bar
358+
*/
359+
function quux (foo, {bar: {baz}}) {
360+
361+
}
362+
`,
363+
settings: {
364+
jsdoc: {
365+
exemptDestructuredRootsFromChecks: true,
366+
},
367+
},
368+
},
245369
],
246370
};

‎test/rules/assertions/requireParamType.js

+124
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,96 @@ export default {
149149
},
150150
},
151151
},
152+
{
153+
code: `
154+
/**
155+
* @param {number} foo
156+
* @param root
157+
* @param {boolean} baz
158+
*/
159+
function quux (foo, {bar}, baz) {
160+
161+
}
162+
`,
163+
errors: [
164+
{
165+
line: 4,
166+
message: 'Missing root type for @param.',
167+
},
168+
],
169+
options: [
170+
{
171+
setDefaultDestructuredRootType: true,
172+
},
173+
],
174+
output: `
175+
/**
176+
* @param {number} foo
177+
* @param {object} root
178+
* @param {boolean} baz
179+
*/
180+
function quux (foo, {bar}, baz) {
181+
182+
}
183+
`,
184+
},
185+
{
186+
code: `
187+
/**
188+
* @param {number} foo
189+
* @param root
190+
* @param {boolean} baz
191+
*/
192+
function quux (foo, {bar}, baz) {
193+
194+
}
195+
`,
196+
errors: [
197+
{
198+
line: 4,
199+
message: 'Missing root type for @param.',
200+
},
201+
],
202+
options: [
203+
{
204+
defaultDestructuredRootType: 'Object',
205+
setDefaultDestructuredRootType: true,
206+
},
207+
],
208+
output: `
209+
/**
210+
* @param {number} foo
211+
* @param {Object} root
212+
* @param {boolean} baz
213+
*/
214+
function quux (foo, {bar}, baz) {
215+
216+
}
217+
`,
218+
},
219+
{
220+
code: `
221+
/**
222+
* @param {number} foo
223+
* @param root
224+
* @param {boolean} baz
225+
*/
226+
function quux (foo, {bar}, baz) {
227+
228+
}
229+
`,
230+
errors: [
231+
{
232+
line: 4,
233+
message: 'Missing JSDoc @param "root" type.',
234+
},
235+
],
236+
options: [
237+
{
238+
setDefaultDestructuredRootType: false,
239+
},
240+
],
241+
},
152242
],
153243
valid: [
154244
{
@@ -204,5 +294,39 @@ export default {
204294
*/
205295
`,
206296
},
297+
{
298+
code: `
299+
/**
300+
* @param {number} foo
301+
* @param root
302+
* @param {boolean} baz
303+
*/
304+
function quux (foo, {bar}, baz) {
305+
306+
}
307+
`,
308+
settings: {
309+
jsdoc: {
310+
exemptDestructuredRootsFromChecks: true,
311+
},
312+
},
313+
},
314+
{
315+
code: `
316+
/**
317+
* @param {number} foo
318+
* @param root
319+
* @param root.bar
320+
*/
321+
function quux (foo, {bar: {baz}}) {
322+
323+
}
324+
`,
325+
settings: {
326+
jsdoc: {
327+
exemptDestructuredRootsFromChecks: true,
328+
},
329+
},
330+
},
207331
],
208332
};

0 commit comments

Comments
 (0)
Please sign in to comment.