UNPKG

eslint-plugin-sonarjs

Version:
112 lines 4.77 kB
"use strict"; /* * eslint-plugin-sonarjs * Copyright (C) 2018 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // https://jira.sonarsource.com/browse/RSPEC-3699 const nodes_1 = require("../utils/nodes"); function isReturnValueUsed(callExpr, context) { const parent = nodes_1.getParent(context); if (!parent) { return false; } if (parent.type === "LogicalExpression") { return parent.left === callExpr; } if (parent.type === "SequenceExpression") { return parent.expressions[parent.expressions.length - 1] === callExpr; } if (parent.type === "ConditionalExpression") { return parent.test === callExpr; } return (parent.type !== "ExpressionStatement" && parent.type !== "ArrowFunctionExpression" && parent.type !== "UnaryExpression" && parent.type !== "AwaitExpression" && parent.type !== "ReturnStatement" && parent.type !== "ThrowStatement"); } const rule = { meta: { type: "problem", }, create(context) { const callExpressionsToCheck = new Map(); const functionsWithReturnValue = new Set(); return { CallExpression(node) { const callExpr = node; if (!isReturnValueUsed(callExpr, context)) { return; } const scope = context.getScope(); const reference = scope.references.find(ref => ref.identifier === callExpr.callee); if (reference && reference.resolved) { const variable = reference.resolved; if (variable.defs.length === 1) { const definition = variable.defs[0]; if (definition.type === "FunctionName") { callExpressionsToCheck.set(reference.identifier, definition.node); } else if (definition.type === "Variable") { const { init } = definition.node; if (init && (nodes_1.isFunctionExpression(init) || nodes_1.isArrowFunctionExpression(init))) { callExpressionsToCheck.set(reference.identifier, init); } } } } }, ReturnStatement(node) { const returnStmt = node; if (returnStmt.argument) { const ancestors = [...context.getAncestors()].reverse(); const functionNode = ancestors.find(node => node.type === "FunctionExpression" || node.type === "FunctionDeclaration" || node.type === "ArrowFunctionExpression"); functionsWithReturnValue.add(functionNode); } }, ArrowFunctionExpression(node) { const arrowFunc = node; if (arrowFunc.expression) { functionsWithReturnValue.add(arrowFunc); } }, ":function"(node) { const func = node; if (func.async || func.generator || (nodes_1.isBlockStatement(func.body) && func.body.body.length === 0)) { functionsWithReturnValue.add(func); } }, "Program:exit"() { callExpressionsToCheck.forEach((functionDeclaration, callee) => { if (!functionsWithReturnValue.has(functionDeclaration)) { context.report({ message: `Remove this use of the output from "{{name}}"; "{{name}}" doesn't return anything.`, node: callee, data: { name: callee.name }, }); } }); }, }; }, }; module.exports = rule; //# sourceMappingURL=no-use-of-empty-return-value.js.map