diff --git a/.README/rules/require-jsdoc.md b/.README/rules/require-jsdoc.md
index b04e380ef..857dfd234 100644
--- a/.README/rules/require-jsdoc.md
+++ b/.README/rules/require-jsdoc.md
@@ -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`
diff --git a/README.md b/README.md
index 0c19b8472..e42906ad2 100644
--- a/README.md
+++ b/README.md
@@ -10064,12 +10064,20 @@ 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
@@ -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:
@@ -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() {
}
diff --git a/src/jsdocUtils.js b/src/jsdocUtils.js
index 142e659f9..34173a6dd 100644
--- a/src/jsdocUtils.js
+++ b/src/jsdocUtils.js
@@ -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;
@@ -1146,6 +1157,9 @@ const exemptSpeciaMethods = (jsdoc, node, context, schema) => {
(schemaProperties[prop] && schemaProperties[prop].default);
};
+ const checkGetters = hasSchemaOption('checkGetters');
+ const checkSetters = hasSchemaOption('checkSetters');
+
return !hasSchemaOption('checkConstructors') &&
(
isConstructor(node) ||
@@ -1153,10 +1167,14 @@ const exemptSpeciaMethods = (jsdoc, node, context, schema) => {
'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)
+ );
};
/**
diff --git a/src/rules/requireJsdoc.js b/src/rules/requireJsdoc.js
index cf30438e6..93cf19348 100644
--- a/src/rules/requireJsdoc.js
+++ b/src/rules/requireJsdoc.js
@@ -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: {
diff --git a/test/rules/assertions/requireJsdoc.js b/test/rules/assertions/requireJsdoc.js
index d194c74cc..76227836a 100644
--- a/test/rules/assertions/requireJsdoc.js
+++ b/test/rules/assertions/requireJsdoc.js
@@ -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: `
@@ -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 {