Skip to content

Add support for checking destructured properties and TypeScript literal object types #498

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 81 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
d8efac9
add support for checking destructuring props and TS object literal props
dstaley Feb 29, 2020
685ab49
remove duplicate test case
dstaley Feb 29, 2020
3971ce1
add support for checking destructuring props and TS object literal props
dstaley Feb 29, 2020
a868a34
remove duplicate test case
dstaley Feb 29, 2020
e01c255
chore: update devDep. (typescript-eslint/parser)
brettz9 Mar 5, 2020
164f9f2
add support for nested destructuring
dstaley Mar 9, 2020
5b381be
Merge branch 'ds/destructuring' of https://github.com/dstaley/eslint-…
dstaley Mar 9, 2020
edda45b
update test case
dstaley Mar 9, 2020
dd5bb1c
add newline
dstaley Mar 9, 2020
521ab61
disable no-param-reassign in reduce
dstaley Mar 9, 2020
2b533a0
remove code introduced in merge
dstaley Mar 9, 2020
d571984
improve test coverage
dstaley Mar 9, 2020
af8651a
fix linting errors
dstaley Mar 9, 2020
5498cab
update README
dstaley Mar 9, 2020
16b7c00
- Refactoring: Avoid need for intermediate variable (and for eslint r…
brettz9 Mar 10, 2020
8c3cda4
- Only declare constant if known to be needed
brettz9 Mar 10, 2020
db1f8c2
refactor: remove unnecessary code; remove now unneeded ignore statements
brettz9 Mar 10, 2020
cf58362
- Explain reason for ignore
brettz9 Mar 10, 2020
ebe2dcf
Todo re: removing `Object.assign` after bumping Node
brettz9 Mar 10, 2020
50162e6
remove leftover debugging code
dstaley Mar 10, 2020
6a6ccf1
restore removed default property value
dstaley Mar 10, 2020
aedde8a
- Set let variable only when needed
brettz9 Mar 11, 2020
7889c06
- Only initialize when needed
brettz9 Mar 11, 2020
e987c81
- Prefer Object.values over lodash; simplify
brettz9 Mar 11, 2020
d8481bb
- allow fallback for `tagNamePreference` message if missing
brettz9 Mar 11, 2020
8deb259
- Document how one can allow aliases along with a main tag name
brettz9 Mar 11, 2020
07b485e
- Add passing example of using self-referential alias
brettz9 Mar 11, 2020
ff6f801
Merge branch 'master' into ds/destructuring
brettz9 Mar 12, 2020
ed37c17
allow configuration of unnamed root base
dstaley Mar 17, 2020
c0d4076
add option to disable fixer for require-param
dstaley Mar 17, 2020
fbd89ee
Merge branch 'master' into ds/destructuring
brettz9 Mar 17, 2020
160993b
Merge branch 'master' into ds/destructuring
brettz9 Mar 18, 2020
4f70748
Merge branch 'master' into ds/destructuring
brettz9 Mar 18, 2020
232b061
Merge branch 'master' into ds/destructuring
brettz9 Mar 22, 2020
b8ef1ae
Merge
brettz9 Apr 20, 2020
94c1691
Merge branch 'master' into ds/destructuring
brettz9 Apr 29, 2020
b1551df
Merge branch 'master' into ds/destructuring
brettz9 May 3, 2020
a5c77a2
docs(require-property); add minor doc fix
brettz9 May 3, 2020
97fb647
Merge branch 'master' into ds/destructuring
brettz9 May 3, 2020
6f53f90
- Docs(require-param): add fixer details
brettz9 May 4, 2020
1de7344
- Add more complex example
brettz9 May 4, 2020
12025a3
- Docs: Add Rest Element insertion and Object Rest Property sections …
brettz9 May 4, 2020
8334f3d
Merge branch 'master' into ds/destructuring
brettz9 May 4, 2020
ffb19b2
- Docs (check-param-names): add docs on destructuring; add `checkRest…
brettz9 May 4, 2020
0013651
Merge branch 'master' into ds/destructuring
brettz9 May 5, 2020
a828002
Merge branch 'master' into ds/destructuring
brettz9 May 6, 2020
808570d
- Add `autoIncrementBase` option
brettz9 May 6, 2020
20cfe73
INCOMPLETE: Fix to ensure inserting root when not present (with or wi…
brettz9 May 6, 2020
fc8b240
Merge branch 'master' into ds/destructuring
brettz9 May 6, 2020
b335831
test(require-param): check renamed destructured param (with default)
brettz9 May 6, 2020
7ea5a60
- Revert to use single name, but insert potentially more than once
brettz9 May 6, 2020
58889ae
Merge branch 'master' into ds/destructuring
brettz9 May 6, 2020
8dedc32
- Handling for default params
brettz9 May 7, 2020
28d8363
- Simplify `findExpectedIndex` (at least for now)
brettz9 May 7, 2020
746b3e0
Ensure indent is relative to applicable node, not whole source code; …
brettz9 May 7, 2020
2f0ed6e
- Insert early params before other subsequent params with proper docs
brettz9 May 7, 2020
8104fa9
adjust test expectations
brettz9 May 7, 2020
83c0788
simplify
brettz9 May 7, 2020
70e510f
- Avoid root if already added
brettz9 May 7, 2020
bcc0df2
- Avoid checking new additions for index determination
brettz9 May 7, 2020
8d311d9
- Remove empty params
brettz9 May 7, 2020
35088cb
fix(require-param): allow checking for `@arg` jsdoc param names if pr…
brettz9 May 7, 2020
98dee25
- Adjust test (inherent limitation of only checking preferred tag names)
brettz9 May 7, 2020
7d40be5
- Correct test expectation for destructured array
brettz9 May 7, 2020
f70b1ee
fix array destructuring
brettz9 May 7, 2020
3a6e3e3
- update readme
brettz9 May 7, 2020
2952429
test(check-param-names): adjust tests for defaulting object and array…
brettz9 May 7, 2020
45a79fd
- Remove unused code
brettz9 May 7, 2020
cfc45f8
- require parent on type annotations
brettz9 May 7, 2020
8de6c44
- Adjust `unnamedRootBase` behavior
brettz9 May 7, 2020
e0722ce
- Implement `enableRootFixer`
brettz9 May 7, 2020
9e7cfaa
INCOMPLETE: Implement/get tests/coverage passing
brettz9 May 7, 2020
a0f0fa6
- Return object with rest element so metadata can be used
brettz9 May 7, 2020
27795c3
- Begin work on reporting back whether rest is a property
brettz9 May 7, 2020
7ce31e0
feat(check-param-names): `checkRestProperty` (and docs/tests)
brettz9 May 8, 2020
d841e64
feat(require-param); `checkRestProperty` option
brettz9 May 8, 2020
06add2f
feat(require-param, check-param-names): `checkTypesPattern` (with doc…
brettz9 May 8, 2020
d906d1b
feat(check-param-names, require-param): check (and for require-param,…
brettz9 May 8, 2020
3da81f4
Merge branch 'destructured-squashed' into ds/destructuring
brettz9 May 8, 2020
9d299a7
- Prevent adding `...any` for rest properties
brettz9 May 9, 2020
9d2c793
chore: update to eslint 7
brettz9 May 9, 2020
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
55 changes: 34 additions & 21 deletions .README/rules/check-param-names.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,41 @@

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

#### Destructuring

Note that by default the rule will not report parameters present on the docs
but non-existing on the function signature when an object rest property is part
of that function signature since the seemingly non-existing properties might
actually be a part of the object rest property.

```js
/**
* @param options
* @param options.foo
*/
function quux ({foo, ...extra}) {}
```

To require that `extra` be documented--and that any extraneous properties
get reported--e.g., if there had been a `@param options.bar` above--you
can use the `checkRestProperty` option which insists that the rest
property be documented (and that there be no other implicit properties).
Note, however, that jsdoc [does not appear](https://github.com/jsdoc/jsdoc/issues/1773)
to currently support syntax or output to distinguish rest properties from
other properties, so in looking at the docs alone without looking at the
function signature, the disadvantage of enabling this option is that it
may appear that there is an actual property named `extra`.

#### Options

##### `checkRestProperty`

See the "Destructuring" section. Defaults to `false`.

##### `checkTypesPattern`

See `require-param` under the option of the same name.

##### `allowExtraTrailingParamDocs`

If set to `true`, this option will allow extra `@param` definitions (e.g.,
Expand All @@ -14,27 +47,7 @@ their presence within the function signature. Other inconsistencies between
|||
|---|---|
|Context|`ArrowFunctionExpression`, `FunctionDeclaration`, `FunctionExpression`|
|Options|`allowExtraTrailingParamDocs`|
|Options|`allowExtraTrailingParamDocs`, `checkRestProperty`, `checkTypesPattern`|
|Tags|`param`|

<!-- assertions checkParamNames -->

#### Deconstructing Function Parameter

`eslint-plugin-jsdoc` does not validate names of parameters in function deconstruction, e.g.

```js
/**
* @param foo
*/
function quux ({
a,
b
}) {

}
```

`{a, b}` is an [`ObjectPattern`](https://github.com/estree/estree/blob/master/es2015.md#objectpattern) AST type and does not have a name. Therefore, the associated parameter in JSDoc block can have any name.

Likewise for the pattern `[a, b]` which is an [`ArrayPattern`](https://github.com/estree/estree/blob/master/es2015.md#arraypattern).
305 changes: 303 additions & 2 deletions .README/rules/require-param.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,279 @@

Requires that all function parameters are documented.

#### Fixer

Adds `@param <name>` for each tag present in the function signature but
missing in the jsdoc. Can be disabled by setting the `enableFixer`
option to `false`.

##### Destructured object and array naming

When the fixer is applied to destructured objects, only the input name is
used.

So for:

```js
/**
* @param cfg
*/
function quux ({foo: bar, baz: bax = 5}) {
}
```

..the fixed jsdoc will be:

```js
/**
* @param cfg
* @param cfg.foo
* @param cfg.baz
*/
```

This is because the input to the function is the relevant item for
understanding the function's input, not how the variable is renamed
for internal use (the signature itself documents that).

For destructured arrays, the input name is merely the array index.

So for:

```js
/**
* @param cfg
*/
function quux ([foo, bar]) {
}
```

..the fixed jsdoc will be:

```js
/**
* @param cfg
* @param cfg.0
* @param cfg.1
*/
```

##### Missing root fixing

Note that unless `enableRootFixer` (or `enableFixer`) is set to `false`,
missing roots will be added and auto-incremented. The default behavior
is for "root" to be auto-inserted for missing roots, followed by a
0-based auto-incrementing number.

So for:

```js
function quux ({foo}, {bar}, {baz}) {
}
```

...the default jsdoc that would be added if the fixer is enabled would be:

```js
/**
* @param root0
* @param root0.foo
* @param root1
* @param root1.bar
* @param root2
* @param root2.baz
*/
```

The name of "root" can be configured with `unnamedRootBase` (which also allows
cycling through a list of multiple root names before there is need for any
numeric component).

And one can have the count begin at another number (e.g., `1`) by changing
`autoIncrementBase` from the default of `0`.

##### Rest Element (`RestElement`) insertions

The fixer will automatically report/insert [jsdoc repeatable parameters](https://jsdoc.app/tags-param.html#multiple-types-and-repeatable-parameters) if missing.

```js
/**
* @param {GenericArray} cfg
* @param {number} cfg.0
*/
function baar ([a, ...extra]) {
//
}
```

..becomes:

```js
/**
* @param {GenericArray} cfg
* @param {number} cfg.0
* @param {...any} cfg.1
*/
function baar ([a, ...extra]) {
//
}
```

Note that the type `any` is included since we don't know of any specific
type to use.

To disable such rest element insertions, set `enableRestElementFixer` to
`false`.

Note too that the following will be reported even though there is an item
corresponding to `extra`:

```js
/**
* @param {GenericArray} cfg
* @param {number} cfg.0
* @param {any} cfg.1
*/
function baar ([a, ...extra]) {
//
}
```

...because it does not use the `...` syntax in the type.

##### Object Rest Property insertions

If the `checkRestProperty` option is set to `true` (`false` by default),
missing rest properties will be reported with documentation auto-inserted:

```js
/**
* @param cfg
* @param cfg.num
*/
function quux ({num, ...extra}) {
}
```

...becomes:

```js
/**
* @param cfg
* @param cfg.num
* @param cfg.extra
*/
function quux ({num, ...extra}) {
}
```

You may wish to manually note in your jsdoc for `extra` that this is a
rest property, however, as jsdoc [does not appear](https://github.com/jsdoc/jsdoc/issues/1773)
to currently support syntax or output to distinguish rest properties from
other properties, so in looking at the docs alone without looking at the
function signature, it may appear that there is an actual property named
`extra`.

#### Options

An options object accepts two optional properties:
An options object accepts the following optional properties:

##### `enableFixer`

Whether to enable the fixer. Defaults to `true`.

##### `enableRootFixer`

Whether to enable the auto-adding of incrementing roots (see the "Fixer"
section). Defaults to `true`. Has no effect if `enableFixer` is set to
`false`.

##### `enableRestElementFixer`

Whether to enable the rest element fixer (see
"Rest Element (`RestElement`) insertions"). Defaults to `true`.

##### `checkRestProperty`

If set to `true`, will report (and add fixer insertions) for missing rest
properties. Defaults to `false`.

If set to `true`, note that you can still document the subproperties of the
rest property using other jsdoc features, e.g., `@typedef`:

```js
/**
* @typedef ExtraOptions
* @property innerProp1
* @property innerProp2
*/

/**
* @param cfg
* @param cfg.num
* @param {ExtraOptions} extra
*/
function quux ({num, ...extra}) {
}
```

Setting this option to `false` (the default) may be useful in cases where
you already have separate `@param` definitions for each of the properties
within the rest property.

For example, with the option disabled, this will not give an error despite
`extra` not having any definition:

```js
/**
* @param cfg
* @param cfg.num
*/
function quux ({num, ...extra}) {
}
```

Nor will this:

```js
/**
* @param cfg
* @param cfg.num
* @param cfg.innerProp1
* @param cfg.innerProp2
*/
function quux ({num, ...extra}) {
}
```

##### `autoIncrementBase`

Numeric to indicate the number at which to begin auto-incrementing roots.
Defaults to `0`.

##### `unnamedRootBase`

An array of root names to use in the fixer when roots are missing. Defaults
to `['root']`. Note that only when all items in the array besides the last
are exhausted will auto-incrementing occur. So, with `unnamedRootBase: ['arg', 'config']`, the following:

```js
function quux ({foo}, [bar], {baz}) {
}
```

...will get the following jsdoc block added:

```js
/**
* @param arg
* @param arg.foo
* @param config0
* @param config0.0 (`bar`)
* @param config1
* @param config1.baz
*/
```

##### `exemptedBy`

Expand All @@ -14,6 +284,37 @@ avoids the need for a `@param`. Defaults to an array with
so be sure to add back `inheritdoc` if you wish its presence to cause
exemption of the rule.

##### `checkTypesPattern`

When one specifies a type, unless it is of a generic type, like `object`
or `array`, it may be considered unnecessary to have that object's
destructured components required, especially where generated docs will
link back to the specified type. For example:

```js
/**
* @param {SVGRect} bbox - a SVGRect
*/
export const bboxToObj = function ({x, y, width, height}) {
return {x, y, width, height};
};
```

By default `checkTypesPattern` is set to
`/^(?:[oO]bject|[aA]rray|PlainObject|Generic(?:Object|Array))$/`,
meaning that destructuring will be required only if the type of the `@param`
(the text between curly brackets) is a match for "Object" or "Array" (with or
without initial caps), "PlainObject", or "GenericObject", "GenericArray" (or
if no type is present). So in the above example, the lack of a match will
mean that no complaint will be given about the undocumented destructured
parameters.

Note that the `/` delimiters are optional, but necessary to add flags.

You could set this regular expression to a more expansive list, or you
could restrict it such that even types matching those strings would not
need destructuring.

##### `contexts`

Set this to an array of strings representing the AST context
Expand All @@ -39,7 +340,7 @@ A value indicating whether getters should be checked. Defaults to `false`.
| Context | `ArrowFunctionExpression`, `FunctionDeclaration`, `FunctionExpression`; others when `contexts` option enabled |
| Tags | `param` |
| Aliases | `arg`, `argument` |
| Options | `contexts`, `exemptedBy`, `checkConstructors`, `checkGetters`, `checkSetters` |
| Options | `autoIncrementBase`, `contexts`, `enableFixer`, `enableRootFixer`, `enableRestElementFixer`, `checkRestProperty`, `exemptedBy`, `checkConstructors`, `checkGetters`, `checkSetters`, `checkTypesPattern`, `unnamedRootBase` |
| Settings | `overrideReplacesDocs`, `augmentsExtendsReplacesDocs`, `implementsReplacesDocs` |

<!-- assertions requireParam -->
Loading