Skip to content

Commit

Permalink
feat(require-jsdoc): allow checking for getter or setter only; fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
brettz9 committed Feb 21, 2021
1 parent 88655b3 commit 937d65e
Show file tree
Hide file tree
Showing 5 changed files with 306 additions and 10 deletions.
12 changes: 10 additions & 2 deletions .README/rules/require-jsdoc.md
Expand Up @@ -73,11 +73,19 @@ no parameters or return values are found.

##### `checkGetters`

A value indicating whether getters should be checked. Defaults to `false`.
A value indicating whether getters should be checked. Besides setting as a
boolean, this option can be set to the string `"no-setter"` to indicate that
getters should be checked but only when there is no setter. This may be useful
if one only wishes documentation on one of the two accessors. Defaults to
`false`.

##### `checkSetters`

A value indicating whether setters should be checked. Defaults to `false`.
A value indicating whether setters should be checked. Besides setting as a
boolean, this option can be set to the string `"no-getter"` to indicate that
setters should be checked but only when there is no getter. This may be useful
if one only wishes documentation on one of the two accessors. Defaults to
`false`.

##### `enableFixer`

Expand Down
74 changes: 72 additions & 2 deletions README.md
Expand Up @@ -10064,12 +10064,20 @@ no parameters or return values are found.
<a name="eslint-plugin-jsdoc-rules-require-jsdoc-options-22-checkgetters-1"></a>
##### <code>checkGetters</code>
A value indicating whether getters should be checked. Defaults to `false`.
A value indicating whether getters should be checked. Besides setting as a
boolean, this option can be set to the string `"no-setter"` to indicate that
getters should be checked but only when there is no setter. This may be useful
if one only wishes documentation on one of the two accessors. Defaults to
`false`.
<a name="eslint-plugin-jsdoc-rules-require-jsdoc-options-22-checksetters-1"></a>
##### <code>checkSetters</code>
A value indicating whether setters should be checked. Defaults to `false`.
A value indicating whether setters should be checked. Besides setting as a
boolean, this option can be set to the string `"no-getter"` to indicate that
setters should be checked but only when there is no getter. This may be useful
if one only wishes documentation on one of the two accessors. Defaults to
`false`.
<a name="eslint-plugin-jsdoc-rules-require-jsdoc-options-22-enablefixer-2"></a>
##### <code>enableFixer</code>
Expand Down Expand Up @@ -10761,6 +10769,24 @@ requestAnimationFrame(draw)
function bench() {
}
// Message: Missing JSDoc comment.

class Foo {
set aName (val) {}
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"checkSetters":"no-getter","contexts":["MethodDefinition > FunctionExpression"]}]
// Message: Missing JSDoc comment.

class Foo {
get aName () {}
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"checkGetters":"no-setter","contexts":["MethodDefinition > FunctionExpression"]}]
// Message: Missing JSDoc comment.

const obj = {
get aName () {},
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"checkGetters":"no-setter","contexts":["Property > FunctionExpression"]}]
// Message: Missing JSDoc comment.
````

The following patterns are not considered problems:
Expand Down Expand Up @@ -11478,6 +11504,50 @@ class Foo {
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"checkConstructors":false,"require":{"MethodDefinition":true}}]

class Foo {
get aName () {}
set aName (val) {}
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"checkGetters":"no-setter","checkSetters":false,"contexts":["MethodDefinition > FunctionExpression"]}]

const obj = {
get aName () {},
set aName (val) {}
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"checkGetters":"no-setter","checkSetters":false,"contexts":["Property > FunctionExpression"]}]

class Foo {
set aName (val) {}
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"checkSetters":false,"contexts":["MethodDefinition > FunctionExpression"]}]

class Foo {
get aName () {}
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"checkGetters":false,"contexts":["MethodDefinition > FunctionExpression"]}]

class Foo {
/**
*
*/
set aName (val) {}
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"checkSetters":"no-getter","contexts":["MethodDefinition > FunctionExpression"]}]

class Foo {
/**
*
*/
get aName () {}
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"checkGetters":"no-setter","contexts":["MethodDefinition > FunctionExpression"]}]

class Foo {
get aName () {}
set aName (val) {}
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"checkGetters":false,"checkSetters":"no-getter","contexts":["MethodDefinition > FunctionExpression"]}]

class Base {
constructor() {
}
Expand Down
26 changes: 22 additions & 4 deletions src/jsdocUtils.js
Expand Up @@ -1138,6 +1138,17 @@ const isSetter = (node) => {
return node && node.parent.kind === 'set';
};

const hasAccessorPair = (node) => {
const {type, kind: sourceKind, key: {name: sourceName}} = node;
const oppositeKind = sourceKind === 'get' ? 'set' : 'get';

const children = type === 'MethodDefinition' ? 'body' : 'properties';

return node.parent[children].some(({kind, key: {name}}) => {
return kind === oppositeKind && name === sourceName;
});
};

const exemptSpeciaMethods = (jsdoc, node, context, schema) => {
const hasSchemaOption = (prop) => {
const schemaProperties = schema[0].properties;
Expand All @@ -1146,17 +1157,24 @@ const exemptSpeciaMethods = (jsdoc, node, context, schema) => {
(schemaProperties[prop] && schemaProperties[prop].default);
};

const checkGetters = hasSchemaOption('checkGetters');
const checkSetters = hasSchemaOption('checkSetters');

return !hasSchemaOption('checkConstructors') &&
(
isConstructor(node) ||
hasATag(jsdoc, [
'class',
'constructor',
])) ||
!hasSchemaOption('checkGetters') &&
isGetter(node) ||
!hasSchemaOption('checkSetters') &&
isSetter(node);
isGetter(node) && (
!checkGetters ||
checkGetters === 'no-setter' && hasAccessorPair(node.parent)
) ||
isSetter(node) && (
!checkSetters ||
checkSetters === 'no-getter' && hasAccessorPair(node.parent)
);
};

/**
Expand Down
20 changes: 18 additions & 2 deletions src/rules/requireJsdoc.js
Expand Up @@ -16,12 +16,28 @@ const OPTIONS_SCHEMA = {
type: 'boolean',
},
checkGetters: {
anyOf: [
{
type: 'boolean',
},
{
enum: ['no-setter'],
type: 'string',
},
],
default: true,
type: 'boolean',
},
checkSetters: {
anyOf: [
{
type: 'boolean',
},
{
enum: ['no-getter'],
type: 'string',
},
],
default: true,
type: 'boolean',
},
contexts: {
items: {
Expand Down
184 changes: 184 additions & 0 deletions test/rules/assertions/requireJsdoc.js
Expand Up @@ -2991,6 +2991,87 @@ function quux (foo) {
}
`,
},
{
code: `
class Foo {
set aName (val) {}
}
`,
errors: [
{
line: 3,
message: 'Missing JSDoc comment.',
},
],
options: [
{
checkSetters: 'no-getter',
contexts: ['MethodDefinition > FunctionExpression'],
},
],
output: `
class Foo {
/**
*
*/
set aName (val) {}
}
`,
},
{
code: `
class Foo {
get aName () {}
}
`,
errors: [
{
line: 3,
message: 'Missing JSDoc comment.',
},
],
options: [
{
checkGetters: 'no-setter',
contexts: ['MethodDefinition > FunctionExpression'],
},
],
output: `
class Foo {
/**
*
*/
get aName () {}
}
`,
},
{
code: `
const obj = {
get aName () {},
}
`,
errors: [
{
line: 3,
message: 'Missing JSDoc comment.',
},
],
options: [
{
checkGetters: 'no-setter',
contexts: ['Property > FunctionExpression'],
},
],
output: `
const obj = {
/**
*
*/
get aName () {},
}
`,
},
],
valid: [{
code: `
Expand Down Expand Up @@ -4539,6 +4620,109 @@ function quux (foo) {
},
],
},
{
code: `
class Foo {
get aName () {}
set aName (val) {}
}
`,
options: [
{
checkGetters: 'no-setter',
checkSetters: false,
contexts: ['MethodDefinition > FunctionExpression'],
},
],
},
{
code: `
const obj = {
get aName () {},
set aName (val) {}
}
`,
options: [
{
checkGetters: 'no-setter',
checkSetters: false,
contexts: ['Property > FunctionExpression'],
},
],
},
{
code: `
class Foo {
set aName (val) {}
}
`,
options: [
{
checkSetters: false,
contexts: ['MethodDefinition > FunctionExpression'],
},
],
},
{
code: `
class Foo {
get aName () {}
}
`,
options: [
{
checkGetters: false,
contexts: ['MethodDefinition > FunctionExpression'],
},
],
},
{
code: `
class Foo {
/**
*
*/
set aName (val) {}
}
`,
options: [
{
checkSetters: 'no-getter',
contexts: ['MethodDefinition > FunctionExpression'],
},
],
},
{
code: `
class Foo {
/**
*
*/
get aName () {}
}
`,
options: [
{
checkGetters: 'no-setter',
contexts: ['MethodDefinition > FunctionExpression'],
},
],
},
{
code: `
class Foo {
get aName () {}
set aName (val) {}
}
`,
options: [
{
checkGetters: false,
checkSetters: 'no-getter',
contexts: ['MethodDefinition > FunctionExpression'],
},
],
},
{
code: `
class Base {
Expand Down

0 comments on commit 937d65e

Please sign in to comment.