diff --git a/.README/rules/require-returns-check.md b/.README/rules/require-returns-check.md
index df3ab3cd8..286fe546c 100644
--- a/.README/rules/require-returns-check.md
+++ b/.README/rules/require-returns-check.md
@@ -11,6 +11,13 @@ Will also report if multiple `@returns` tags are present.
#### Options
+- `exemptGenerators`- Because a generator might be labeled as having a
+ `IterableIterator` `@returns` value (along with an iterator type
+ corresponding to the type of any `yield` statements), projects might wish to
+ leverage `@returns` in generators even without a` return` statement. This
+ option is therefore `true` by default in `typescript` mode (in "jsdoc" mode,
+ one might be more likely to take advantage of `@yields`). Set it to `false`
+ if you wish for a missing `return` to be flagged regardless.
- `exemptAsync` - By default, functions which return a `Promise` that are not
detected as resolving with a non-`undefined` value and `async` functions
(even ones that do not explicitly return a value, as these are returning a
diff --git a/README.md b/README.md
index a4f6c984a..860109549 100644
--- a/README.md
+++ b/README.md
@@ -16120,6 +16120,13 @@ Will also report if multiple `@returns` tags are present.
#### Options
+- `exemptGenerators`- Because a generator might be labeled as having a
+ `IterableIterator` `@returns` value (along with an iterator type
+ corresponding to the type of any `yield` statements), projects might wish to
+ leverage `@returns` in generators even without a` return` statement. This
+ option is therefore `true` by default in `typescript` mode (in "jsdoc" mode,
+ one might be more likely to take advantage of `@yields`). Set it to `false`
+ if you wish for a missing `return` to be flagged regardless.
- `exemptAsync` - By default, functions which return a `Promise` that are not
detected as resolving with a non-`undefined` value and `async` functions
(even ones that do not explicitly return a value, as these are returning a
@@ -16229,6 +16236,21 @@ async function quux() {}
// "jsdoc/require-returns-check": ["error"|"warn", {"exemptAsync":false}]
// Message: JSDoc @returns declaration present but return expression not available in function.
+/**
+ * @returns {IterableIterator}
+ */
+function * quux() {}
+// Settings: {"jsdoc":{"mode":"jsdoc"}}
+// Message: JSDoc @returns declaration present but return expression not available in function.
+
+/**
+ * @returns {IterableIterator}
+ */
+function * quux() {}
+// Settings: {"jsdoc":{"mode":"typescript"}}
+// "jsdoc/require-returns-check": ["error"|"warn", {"exemptGenerators":false}]
+// Message: JSDoc @returns declaration present but return expression not available in function.
+
/**
* @returns {Promise}
*/
@@ -16634,6 +16656,19 @@ function quux () {
return 'abc';
}
// "jsdoc/require-returns-check": ["error"|"warn", {"reportMissingReturnForUndefinedTypes":true}]
+
+/**
+ * @returns {IterableIterator}
+ */
+function * quux() {}
+// Settings: {"jsdoc":{"mode":"typescript"}}
+
+/**
+ * @returns {IterableIterator}
+ */
+function * quux() {}
+// Settings: {"jsdoc":{"mode":"jsdoc"}}
+// "jsdoc/require-returns-check": ["error"|"warn", {"exemptGenerators":true}]
````
diff --git a/src/rules/requireReturnsCheck.js b/src/rules/requireReturnsCheck.js
index c745a91d4..12b30a481 100755
--- a/src/rules/requireReturnsCheck.js
+++ b/src/rules/requireReturnsCheck.js
@@ -30,12 +30,14 @@ const canSkip = (utils, settings) => {
export default iterateJsdoc(({
context,
+ node,
report,
settings,
utils,
}) => {
const {
exemptAsync = true,
+ exemptGenerators = settings.mode === 'typescript',
reportMissingReturnForUndefinedTypes = false,
} = context.options[0] || {};
@@ -64,7 +66,9 @@ export default iterateJsdoc(({
}
// In case a return value is declared in JSDoc, we also expect one in the code.
- if ((reportMissingReturnForUndefinedTypes || utils.hasDefinedTypeTag(tags[0])) && !utils.hasValueOrExecutorHasNonEmptyResolveValue(exemptAsync)) {
+ if ((reportMissingReturnForUndefinedTypes || utils.hasDefinedTypeTag(tags[0])) && !utils.hasValueOrExecutorHasNonEmptyResolveValue(
+ exemptAsync,
+ ) && (!exemptGenerators || !node.generator)) {
report(`JSDoc @${tagName} declaration present but return expression not available in function.`);
}
}, {
@@ -81,6 +85,9 @@ export default iterateJsdoc(({
default: true,
type: 'boolean',
},
+ exemptGenerators: {
+ type: 'boolean',
+ },
reportMissingReturnForUndefinedTypes: {
default: false,
type: 'boolean',
diff --git a/test/rules/assertions/requireReturnsCheck.js b/test/rules/assertions/requireReturnsCheck.js
index 9f8a648a9..77dbd7ec6 100755
--- a/test/rules/assertions/requireReturnsCheck.js
+++ b/test/rules/assertions/requireReturnsCheck.js
@@ -172,6 +172,53 @@ export default {
ecmaVersion: 8,
},
},
+ {
+ code: `
+ /**
+ * @returns {IterableIterator}
+ */
+ function * quux() {}
+ `,
+ errors: [
+ {
+ line: 2,
+ message: 'JSDoc @returns declaration present but return expression not available in function.',
+ },
+ ],
+ parserOptions: {
+ ecmaVersion: 8,
+ },
+ settings: {
+ jsdoc: {
+ mode: 'jsdoc',
+ },
+ },
+ },
+ {
+ code: `
+ /**
+ * @returns {IterableIterator}
+ */
+ function * quux() {}
+ `,
+ errors: [
+ {
+ line: 2,
+ message: 'JSDoc @returns declaration present but return expression not available in function.',
+ },
+ ],
+ options: [{
+ exemptGenerators: false,
+ }],
+ parserOptions: {
+ ecmaVersion: 8,
+ },
+ settings: {
+ jsdoc: {
+ mode: 'typescript',
+ },
+ },
+ },
{
code: `
/**
@@ -791,5 +838,40 @@ export default {
reportMissingReturnForUndefinedTypes: true,
}],
},
+ {
+ code: `
+ /**
+ * @returns {IterableIterator}
+ */
+ function * quux() {}
+ `,
+ parserOptions: {
+ ecmaVersion: 8,
+ },
+ settings: {
+ jsdoc: {
+ mode: 'typescript',
+ },
+ },
+ },
+ {
+ code: `
+ /**
+ * @returns {IterableIterator}
+ */
+ function * quux() {}
+ `,
+ options: [{
+ exemptGenerators: true,
+ }],
+ parserOptions: {
+ ecmaVersion: 8,
+ },
+ settings: {
+ jsdoc: {
+ mode: 'jsdoc',
+ },
+ },
+ },
],
};