@arabasta/eslint-plugin-tsoa
Version:
ESLint plugin for tsoa rules
99 lines (98 loc) • 4.22 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const type_utils_1 = require("@typescript-eslint/type-utils");
const utils_1 = require("@typescript-eslint/utils");
const utils_2 = require("../utils");
exports.default = (0, utils_2.createRule)({
name: 'require-jsdoc-returns',
meta: {
messages: {
returnsIsMissing: "Missing JSDoc '@returns' declaration",
returnsIsNotAllowed: "JSDoc '@returns' declaration is not allowed on methods that return 'void' or 'undefined'",
returnsDescriptionIsMissing: "Missing JSDoc '@returns' description",
},
type: 'problem',
docs: {
description: 'require return statements to be documented',
recommended: true,
requiresTypeChecking: true,
},
schema: [
{
type: 'object',
additionalProperties: false,
properties: {
disallowOnVoidOrUndefined: {
type: 'boolean',
description: "Whether to disallow JSDoc's '@returns' declaration on methods that return 'void' or 'undefined'.",
},
},
},
],
},
defaultOptions: [
{
disallowOnVoidOrUndefined: true,
},
],
create(context, [{ disallowOnVoidOrUndefined }]) {
const services = utils_1.ESLintUtils.getParserServices(context);
const checker = services.program.getTypeChecker();
const sourceCode = context.sourceCode || context.getSourceCode();
function getFunctionReturnTypeName(node) {
const signatures = services.getTypeAtLocation(node).getCallSignatures();
if (!signatures.length) {
return;
}
const methodReturnType = checker.getReturnTypeOfSignature(signatures[0]);
if ((0, type_utils_1.isPromiseLike)(services.program, methodReturnType) &&
'resolvedTypeArguments' in methodReturnType &&
Array.isArray(methodReturnType.resolvedTypeArguments) &&
methodReturnType.resolvedTypeArguments.length === 1 &&
methodReturnType.resolvedTypeArguments[0]) {
return (0, type_utils_1.getTypeName)(checker, methodReturnType.resolvedTypeArguments[0]);
}
return (0, type_utils_1.getTypeName)(checker, methodReturnType);
}
return {
MethodDefinition(node) {
const returnType = getFunctionReturnTypeName(node);
const { jsdoc, jsdocNode } = (0, utils_2.parseJSDoc)(sourceCode, node);
if (!jsdoc || !jsdocNode) {
return;
}
const targetTagName = 'returns';
const propertyReturns = jsdoc.tags.filter(({ tag }) => {
return tag === targetTagName;
});
const returnTypeIsUndefinedOrVoid = returnType === 'void' || returnType === 'undefined';
const hasReturnsJSDocDeclaration = propertyReturns.length > 0;
if (returnTypeIsUndefinedOrVoid) {
if (hasReturnsJSDocDeclaration && disallowOnVoidOrUndefined) {
context.report({
node: jsdocNode,
messageId: 'returnsIsNotAllowed',
});
}
return;
}
if (hasReturnsJSDocDeclaration) {
const description = propertyReturns[0].description.trim();
if (description.length === 0) {
context.report({
node,
messageId: 'returnsDescriptionIsMissing',
});
return;
}
}
if (!hasReturnsJSDocDeclaration) {
context.report({
node: jsdocNode,
messageId: 'returnsIsMissing',
});
}
},
};
},
});