UNPKG

@arabasta/eslint-plugin-tsoa

Version:
99 lines (98 loc) 4.22 kB
"use strict"; 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', }); } }, }; }, });