# require-returns
* [Fixer](#user-content-require-returns-fixer)
* [Options](#user-content-require-returns-options)
* [`checkConstructors`](#user-content-require-returns-options-checkconstructors)
* [`checkGetters`](#user-content-require-returns-options-checkgetters)
* [`contexts`](#user-content-require-returns-options-contexts)
* [`enableFixer`](#user-content-require-returns-options-enablefixer)
* [`exemptedBy`](#user-content-require-returns-options-exemptedby)
* [`forceRequireReturn`](#user-content-require-returns-options-forcerequirereturn)
* [`forceReturnsWithAsync`](#user-content-require-returns-options-forcereturnswithasync)
* [`publicOnly`](#user-content-require-returns-options-publiconly)
* [Context and settings](#user-content-require-returns-context-and-settings)
* [Failing examples](#user-content-require-returns-failing-examples)
* [Passing examples](#user-content-require-returns-passing-examples)
Requires that return statements are documented.
Will also report if multiple `@returns` tags are present.
## Fixer
Adds a blank `@returns`.
## Options
A single options object has the following properties.
### checkConstructors
A value indicating whether `constructor`s should
be checked for `@returns` tags. Defaults to `false`.
### checkGetters
Boolean to determine whether getter methods should
be checked for `@returns` tags. Defaults to `true`.
### contexts
Set this to an array of strings representing the AST context
(or objects with optional `context` and `comment` properties) where you wish
the rule to be applied.
`context` defaults to `any` and `comment` defaults to no specific comment context.
Overrides the default contexts (`ArrowFunctionExpression`, `FunctionDeclaration`,
`FunctionExpression`). Set to `"any"` if you want
the rule to apply to any JSDoc block throughout your files (as is necessary
for finding function blocks not attached to a function declaration or
expression, i.e., `@callback` or `@function` (or its aliases `@func` or
`@method`) (including those associated with an `@interface`). This
rule will only apply on non-default contexts when there is such a tag
present and the `forceRequireReturn` option is set or if the
`forceReturnsWithAsync` option is set with a present `@async` tag
(since we are not checking against the actual `return` values in these
cases).
### enableFixer
Whether to enable the fixer to add a blank `@returns`.
Defaults to `false`.
### exemptedBy
Array of tags (e.g., `['type']`) whose presence on the
document block avoids the need for a `@returns`. Defaults to an array
with `inheritdoc`. If you set this array, it will overwrite the default,
so be sure to add back `inheritdoc` if you wish its presence to cause
exemption of the rule.
### forceRequireReturn
Set to `true` to always insist on
`@returns` documentation regardless of implicit or explicit `return`'s
in the function. May be desired to flag that a project is aware of an
`undefined`/`void` return. Defaults to `false`.
### forceReturnsWithAsync
By default `async` functions that do not explicitly
return a value pass this rule as an `async` function will always return a
`Promise`, even if the `Promise` resolves to void. You can force all
`async` functions (including ones with an explicit `Promise` but no
detected non-`undefined` `resolve` value) to require `@return`
documentation by setting `forceReturnsWithAsync` to `true` on the options
object. This may be useful for flagging that there has been consideration
of return type. Defaults to `false`.
### publicOnly
This option will insist that missing `@returns` are only reported for
function bodies / class declarations that are exported from the module.
May be a boolean or object. If set to `true`, the defaults below will be
used. If unset, `@returns` reporting will not be limited to exports.
This object supports the following optional boolean keys (`false` unless
otherwise noted):
- `ancestorsOnly` - Optimization to only check node ancestors to check if node is exported
- `esm` - ESM exports are checked for `@returns` JSDoc comments (Defaults to `true`)
- `cjs` - CommonJS exports are checked for `@returns` JSDoc comments (Defaults to `true`)
- `window` - Window global exports are checked for `@returns` JSDoc comments
## Context and settings
| | |
| -------- | ------- |
| Context | `ArrowFunctionExpression`, `FunctionDeclaration`, `FunctionExpression`; others when `contexts` option enabled |
| Tags | `returns` |
| Aliases | `return` |
|Recommended|true|
| Options |`checkConstructors`, `checkGetters`, `contexts`, `enableFixer`, `exemptedBy`, `forceRequireReturn`, `forceReturnsWithAsync`, `publicOnly`|
| Settings | `ignoreReplacesDocs`, `overrideReplacesDocs`, `augmentsExtendsReplacesDocs`, `implementsReplacesDocs` |
## Failing examples
The following patterns are considered problems:
````ts
/**
*
*/
function quux (foo) {
return foo;
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux (foo) {
return foo;
}
// "jsdoc/require-returns": ["error"|"warn", {"enableFixer":true}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
const foo = () => ({
bar: 'baz'
})
// Message: Missing JSDoc @returns declaration.
/**
*
*/
const foo = bar=>({ bar })
// Message: Missing JSDoc @returns declaration.
/**
*
*/
const foo = bar => bar.baz()
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux (foo) {
return foo;
}
// Settings: {"jsdoc":{"tagNamePreference":{"returns":"return"}}}
// Message: Missing JSDoc @return declaration.
/**
*
*/
async function quux() {
}
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
const quux = async function () {}
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
const quux = async () => {}
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
async function quux () {}
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
}
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
}
// "jsdoc/require-returns": ["error"|"warn", {"contexts":["any"],"forceRequireReturn":true}]
// Message: Missing JSDoc @returns declaration.
/**
* @function
*/
// "jsdoc/require-returns": ["error"|"warn", {"contexts":["any"],"forceRequireReturn":true}]
// Message: Missing JSDoc @returns declaration.
/**
* @callback
*/
// "jsdoc/require-returns": ["error"|"warn", {"contexts":["any"],"forceRequireReturn":true}]
// Message: Missing JSDoc @returns declaration.
const language = {
/**
* @param {string} name
*/
get name() {
return this._name;
}
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
async function quux () {
}
// "jsdoc/require-returns": ["error"|"warn", {"forceReturnsWithAsync":true}]
// Message: Missing JSDoc @returns declaration.
/**
* @function
* @async
*/
// "jsdoc/require-returns": ["error"|"warn", {"contexts":["any"],"forceReturnsWithAsync":true}]
// Message: Missing JSDoc @returns declaration.
/**
* @callback
* @async
*/
// "jsdoc/require-returns": ["error"|"warn", {"contexts":["any"],"forceReturnsWithAsync":true}]
// Message: Missing JSDoc @returns declaration.
/**
* @returns {undefined}
* @returns {void}
*/
function quux (foo) {
return foo;
}
// Message: Found more than one @returns declaration.
/**
* @returns
*/
function quux () {
}
// Settings: {"jsdoc":{"tagNamePreference":{"returns":false}}}
// Message: Unexpected tag `@returns`
/**
* @param foo
*/
function quux (foo) {
return 'bar';
}
// "jsdoc/require-returns": ["error"|"warn", {"exemptedBy":["notPresent"]}]
// Message: Missing JSDoc @returns declaration.
/**
* @param {array} a
*/
async function foo(a) {
return;
}
// "jsdoc/require-returns": ["error"|"warn", {"forceReturnsWithAsync":true}]
// Message: Missing JSDoc @returns declaration.
/**
* @param {array} a
*/
async function foo(a) {
return Promise.all(a);
}
// "jsdoc/require-returns": ["error"|"warn", {"forceReturnsWithAsync":true}]
// Message: Missing JSDoc @returns declaration.
class foo {
/** gets bar */
get bar() {
return 0;
}
}
// "jsdoc/require-returns": ["error"|"warn", {"checkGetters":true}]
// Message: Missing JSDoc @returns declaration.
class TestClass {
/**
*
*/
constructor() {
return new Map();
}
}
// "jsdoc/require-returns": ["error"|"warn", {"checkConstructors":true}]
// Message: Missing JSDoc @returns declaration.
class TestClass {
/**
*
*/
get Test() {
return 0;
}
}
// "jsdoc/require-returns": ["error"|"warn", {"checkGetters":true}]
// Message: Missing JSDoc @returns declaration.
class quux {
/**
*
*/
quux () {
}
}
// "jsdoc/require-returns": ["error"|"warn", {"contexts":["any"],"forceRequireReturn":true}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux (foo) {
return new Promise(function (resolve, reject) {
resolve(foo);
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux (foo) {
return new Promise(function (resolve, reject) {
setTimeout(() => {
resolve(true);
});
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux (foo) {
return new Promise(function (resolve, reject) {
foo(resolve);
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
return new Promise((resolve, reject) => {
while(true) {
resolve(true);
}
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
return new Promise((resolve, reject) => {
do {
resolve(true);
}
while(true)
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
return new Promise((resolve, reject) => {
if (true) {
resolve(true);
}
return;
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
return new Promise((resolve, reject) => {
if (true) {
resolve(true);
}
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
var a = {};
return new Promise((resolve, reject) => {
with (a) {
resolve(true);
}
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
var a = {};
return new Promise((resolve, reject) => {
try {
resolve(true);
} catch (err) {}
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
var a = {};
return new Promise((resolve, reject) => {
try {
} catch (err) {
resolve(true);
}
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
var a = {};
return new Promise((resolve, reject) => {
try {
} catch (err) {
} finally {
resolve(true);
}
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
var a = {};
return new Promise((resolve, reject) => {
switch (a) {
case 'abc':
resolve(true);
}
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
return new Promise((resolve, reject) => {
if (true) {
resolve();
} else {
resolve(true);
}
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
return new Promise((resolve, reject) => {
for (let i = 0; i < 5 ; i++) {
resolve(true);
}
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
return new Promise((resolve, reject) => {
for (const i of obj) {
resolve(true);
}
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
return new Promise((resolve, reject) => {
for (const i in obj) {
resolve(true);
}
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
return new Promise((resolve, reject) => {
if (true) {
return;
} else {
resolve(true);
}
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
return new Promise((resolve, reject) => {
function a () {
resolve(true);
}
a();
});
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {
return new Promise();
}
// "jsdoc/require-returns": ["error"|"warn", {"forceReturnsWithAsync":true}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
async function quux () {
return new Promise();
}
// "jsdoc/require-returns": ["error"|"warn", {"forceReturnsWithAsync":true}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
async function quux () {
return new Promise((resolve, reject) => {});
}
// "jsdoc/require-returns": ["error"|"warn", {"forceReturnsWithAsync":true}]
// Message: Missing JSDoc @returns declaration.
export class A {
/**
* Description.
*/
public f(): string {
return "";
}
}
export interface B {
/**
* Description.
*/
f(): string;
/**
* Description.
*/
g: () => string;
/**
* Description.
*/
h(): void;
/**
* Description.
*/
i: () => void;
}
/**
* Description.
*/
export function f(): string {
return "";
}
// "jsdoc/require-returns": ["error"|"warn", {"contexts":[":not(BlockStatement) > FunctionDeclaration","MethodDefinition","TSMethodSignature","TSPropertySignature > TSTypeAnnotation > TSFunctionType"]}]
// Message: Missing JSDoc @returns declaration.
/**
* @param ms time in millis
*/
export const sleep = (ms: number) =>
new Promise((res) => setTimeout(res, ms));
// Message: Missing JSDoc @returns declaration.
/**
* @param ms time in millis
*/
export const sleep = (ms: number) => {
return new Promise((res) => setTimeout(res, ms));
};
// Message: Missing JSDoc @returns declaration.
/**
* Reads a test fixture.
*/
export function readFixture(path: string): Promise;
// Message: Missing JSDoc @returns declaration.
/**
* Reads a test fixture.
*/
export function readFixture(path: string): void;
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
// Message: Missing JSDoc @returns declaration.
/**
* Reads a test fixture.
*/
export function readFixture(path: string);
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
// Message: Missing JSDoc @returns declaration.
/**
* @param {array} a
*/
async function foo(a) {
return Promise.all(a);
}
// Message: Missing JSDoc @returns declaration.
/**
* Description.
*/
export default async function demo() {
return true;
}
// Message: Missing JSDoc @returns declaration.
/**
*
*/
function quux () {}
class Test {
/**
*
*/
abstract Test(): string;
}
// "jsdoc/require-returns": ["error"|"warn", {"contexts":["FunctionDeclaration",{"context":"TSEmptyBodyFunctionExpression","forceRequireReturn":true}]}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
module.exports = function quux (foo) {
return foo;
}
// "jsdoc/require-returns": ["error"|"warn", {"publicOnly":true}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
const a = function quux (foo) {
return foo;
};
export default a;
// "jsdoc/require-returns": ["error"|"warn", {"publicOnly":true}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
export default function quux (foo) {
return foo;
};
// "jsdoc/require-returns": ["error"|"warn", {"publicOnly":{"ancestorsOnly":true,"esm":true}}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
exports.quux = function quux (foo) {
return foo;
};
// "jsdoc/require-returns": ["error"|"warn", {"publicOnly":{"cjs":true}}]
// Message: Missing JSDoc @returns declaration.
/**
*
*/
window.quux = function quux (foo) {
return foo;
};
// "jsdoc/require-returns": ["error"|"warn", {"publicOnly":{"window":true}}]
// Message: Missing JSDoc @returns declaration.
````
## Passing examples
The following patterns are not considered problems:
````ts
/**
* @returns Foo.
*/
function quux () {
return foo;
}
/**
* @returns Foo.
*/
function quux () {
return foo;
}
// "jsdoc/require-returns": ["error"|"warn", {"contexts":["any"]}]
/**
*
*/
function quux () {
}
/**
*
*/
function quux (bar) {
bar.filter(baz => {
return baz.corge();
})
}
/**
* @returns Array
*/
function quux (bar) {
return bar.filter(baz => {
return baz.corge();
})
}
/**
* @returns Array
*/
const quux = (bar) => bar.filter(({ corge }) => corge())
/**
* @inheritdoc
*/
function quux (foo) {
}
/**
* @override
*/
function quux (foo) {
}
/**
* @constructor
*/
function quux (foo) {
return true;
}
/**
* @implements
*/
function quux (foo) {
return true;
}
/**
* @override
*/
function quux (foo) {
return foo;
}
/**
* @class
*/
function quux (foo) {
return true;
}
/**
* @constructor
*/
function quux (foo) {
}
/**
* @returns {object}
*/
function quux () {
return {a: foo};
}
/**
* @returns {object}
*/
const quux = () => ({a: foo});
/**
* @returns {object}
*/
const quux = () => {
return {a: foo}
};
/**
* @returns {void}
*/
function quux () {
}
/**
* @returns {void}
*/
const quux = () => {
}
/**
* @returns {undefined}
*/
function quux () {
}
/**
* @returns {undefined}
*/
const quux = () => {
}
/**
*
*/
const quux = () => {
}
class Foo {
/**
*
*/
constructor () {
}
}
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
const language = {
/**
* @param {string} name
*/
set name(name) {
this._name = name;
}
}
/**
* @returns {void}
*/
function quux () {
}
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
/**
* @returns {void}
*/
function quux () {
return undefined;
}
/**
* @returns {void}
*/
function quux () {
return undefined;
}
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
/**
* @returns {void}
*/
function quux () {
return;
}
/**
* @returns {void}
*/
function quux () {
return;
}
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
/** @type {RequestHandler} */
function quux (req, res , next) {
return;
}
/**
* @returns {Promise}
*/
async function quux () {
}
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
/**
* @returns {Promise}
*/
async function quux () {
}
// "jsdoc/require-returns": ["error"|"warn", {"forceReturnsWithAsync":true}]
/**
*
*/
async function quux () {}
/**
*
*/
const quux = async function () {}
/**
*
*/
const quux = async () => {}
/** foo class */
class foo {
/** foo constructor */
constructor () {
// =>
this.bar = true;
}
}
export default foo;
/**
*
*/
function quux () {
}
// "jsdoc/require-returns": ["error"|"warn", {"forceReturnsWithAsync":true}]
/**
* @type {MyCallback}
*/
function quux () {
}
// "jsdoc/require-returns": ["error"|"warn", {"exemptedBy":["type"]}]
/**
* @param {array} a
*/
async function foo(a) {
return;
}
/**
*
*/
// "jsdoc/require-returns": ["error"|"warn", {"contexts":["any"]}]
/**
* @async
*/
// "jsdoc/require-returns": ["error"|"warn", {"contexts":["any"]}]
/**
* @function
*/
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
/**
* @callback
*/
// "jsdoc/require-returns": ["error"|"warn", {"forceRequireReturn":true}]
/**
* @function
* @async
*/
// "jsdoc/require-returns": ["error"|"warn", {"forceReturnsWithAsync":true}]
/**
* @callback
* @async
*/
// "jsdoc/require-returns": ["error"|"warn", {"forceReturnsWithAsync":true}]
/**
* @function
*/
// "jsdoc/require-returns": ["error"|"warn", {"contexts":["any"],"forceReturnsWithAsync":true}]
/**
* @callback
*/
// "jsdoc/require-returns": ["error"|"warn", {"contexts":["any"],"forceReturnsWithAsync":true}]
class foo {
get bar() {
return 0;
}
}
// "jsdoc/require-returns": ["error"|"warn", {"checkGetters":false}]
class foo {
/** @returns zero */
get bar() {
return 0;
}
}
// "jsdoc/require-returns": ["error"|"warn", {"checkGetters":true}]
class foo {
/** @returns zero */
get bar() {
return 0;
}
}
// "jsdoc/require-returns": ["error"|"warn", {"checkGetters":false}]
class TestClass {
/**
*
*/
constructor() { }
}
class TestClass {
/**
* @returns A map.
*/
constructor() {
return new Map();
}
}
class TestClass {
/**
*
*/
constructor() { }
}
// "jsdoc/require-returns": ["error"|"warn", {"checkConstructors":false}]
class TestClass {
/**
*
*/
get Test() { }
}
class TestClass {
/**
* @returns A number.
*/
get Test() {
return 0;
}
}
class TestClass {
/**
*
*/
get Test() {
return 0;
}
}
// "jsdoc/require-returns": ["error"|"warn", {"checkGetters":false}]
/**
*
*/
function quux (foo) {
return new Promise(function (resolve, reject) {
resolve();
});
}
/**
*
*/
function quux (foo) {
return new Promise(function (resolve, reject) {
setTimeout(() => {
resolve();
});
});
}
/**
*
*/
function quux (foo) {
return new Promise(function (resolve, reject) {
foo();
});
}
/**
*
*/
function quux (foo) {
return new Promise(function (resolve, reject) {
abc((resolve) => {
resolve(true);
});
});
}
/**
*
*/
function quux (foo) {
return new Promise(function (resolve, reject) {
abc(function (resolve) {
resolve(true);
});
});
}
/**
*
*/
function quux () {
return new Promise((resolve, reject) => {
if (true) {
resolve();
}
});
return;
}
/**
*
*/
function quux () {
return new Promise();
}
/**
* Description.
*/
async function foo() {
return new Promise(resolve => resolve());
}
/**
* @param ms time in millis
*/
export const sleep = (ms: number) =>
new Promise((res) => setTimeout(res, ms));
/**
* @param ms time in millis
*/
export const sleep = (ms: number) => {
return new Promise((res) => setTimeout(res, ms));
};
/**
* Reads a test fixture.
*
* @returns The file contents as buffer.
*/
export function readFixture(path: string): Promise;
/**
* Reads a test fixture.
*
* @returns {void}.
*/
export function readFixture(path: string): void;
/**
* Reads a test fixture.
*/
export function readFixture(path: string): void;
/**
* Reads a test fixture.
*/
export function readFixture(path: string);
/**
*
*/
function quux () {}
class Test {
/**
* @returns {string} The test value
*/
abstract Test(): string;
}
// "jsdoc/require-returns": ["error"|"warn", {"contexts":["FunctionDeclaration",{"context":"TSEmptyBodyFunctionExpression","forceRequireReturn":true}]}]
/**
*
*/
function quux (foo) {
return foo;
}
// "jsdoc/require-returns": ["error"|"warn", {"publicOnly":true}]
````