]> git.proxmox.com Git - pve-eslint.git/blobdiff - eslint/lib/rules/no-constant-condition.js
import 8.23.1 source
[pve-eslint.git] / eslint / lib / rules / no-constant-condition.js
index 0bcb31931e4205bbd695cb46bb4512b32a42b428..2ef687f6dca7ebd83d865896ebc7c80e98c619de 100644 (file)
@@ -5,6 +5,8 @@
 
 "use strict";
 
+const { isConstant } = require("./utils/ast-utils");
+
 //------------------------------------------------------------------------------
 // Helpers
 //------------------------------------------------------------------------------
@@ -19,7 +21,7 @@ module.exports = {
         type: "problem",
 
         docs: {
-            description: "disallow constant expressions in conditions",
+            description: "Disallow constant expressions in conditions",
             recommended: true,
             url: "https://eslint.org/docs/rules/no-constant-condition"
         },
@@ -53,155 +55,6 @@ module.exports = {
         // Helpers
         //--------------------------------------------------------------------------
 
-        /**
-         * Returns literal's value converted to the Boolean type
-         * @param {ASTNode} node any `Literal` node
-         * @returns {boolean | null} `true` when node is truthy, `false` when node is falsy,
-         *  `null` when it cannot be determined.
-         */
-        function getBooleanValue(node) {
-            if (node.value === null) {
-
-                /*
-                 * it might be a null literal or bigint/regex literal in unsupported environments .
-                 * https://github.com/estree/estree/blob/14df8a024956ea289bd55b9c2226a1d5b8a473ee/es5.md#regexpliteral
-                 * https://github.com/estree/estree/blob/14df8a024956ea289bd55b9c2226a1d5b8a473ee/es2020.md#bigintliteral
-                 */
-
-                if (node.raw === "null") {
-                    return false;
-                }
-
-                // regex is always truthy
-                if (typeof node.regex === "object") {
-                    return true;
-                }
-
-                return null;
-            }
-
-            return !!node.value;
-        }
-
-        /**
-         * Checks if a branch node of LogicalExpression short circuits the whole condition
-         * @param {ASTNode} node The branch of main condition which needs to be checked
-         * @param {string} operator The operator of the main LogicalExpression.
-         * @returns {boolean} true when condition short circuits whole condition
-         */
-        function isLogicalIdentity(node, operator) {
-            switch (node.type) {
-                case "Literal":
-                    return (operator === "||" && getBooleanValue(node) === true) ||
-                           (operator === "&&" && getBooleanValue(node) === false);
-
-                case "UnaryExpression":
-                    return (operator === "&&" && node.operator === "void");
-
-                case "LogicalExpression":
-
-                    /*
-                     * handles `a && false || b`
-                     * `false` is an identity element of `&&` but not `||`
-                     */
-                    return operator === node.operator &&
-                             (
-                                 isLogicalIdentity(node.left, operator) ||
-                                 isLogicalIdentity(node.right, operator)
-                             );
-
-                case "AssignmentExpression":
-                    return ["||=", "&&="].includes(node.operator) &&
-                        operator === node.operator.slice(0, -1) &&
-                        isLogicalIdentity(node.right, operator);
-
-                // no default
-            }
-            return false;
-        }
-
-        /**
-         * Checks if a node has a constant truthiness value.
-         * @param {ASTNode} node The AST node to check.
-         * @param {boolean} inBooleanPosition `false` if checking branch of a condition.
-         *  `true` in all other cases
-         * @returns {Bool} true when node's truthiness is constant
-         * @private
-         */
-        function isConstant(node, inBooleanPosition) {
-
-            // node.elements can return null values in the case of sparse arrays ex. [,]
-            if (!node) {
-                return true;
-            }
-            switch (node.type) {
-                case "Literal":
-                case "ArrowFunctionExpression":
-                case "FunctionExpression":
-                case "ObjectExpression":
-                case "ClassExpression":
-                    return true;
-                case "TemplateLiteral":
-                    return (inBooleanPosition && node.quasis.some(quasi => quasi.value.cooked.length)) ||
-                        node.expressions.every(exp => isConstant(exp, inBooleanPosition));
-
-                case "ArrayExpression": {
-                    if (node.parent.type === "BinaryExpression" && node.parent.operator === "+") {
-                        return node.elements.every(element => isConstant(element, false));
-                    }
-                    return true;
-                }
-
-                case "UnaryExpression":
-                    if (
-                        node.operator === "void" ||
-                        node.operator === "typeof" && inBooleanPosition
-                    ) {
-                        return true;
-                    }
-
-                    if (node.operator === "!") {
-                        return isConstant(node.argument, true);
-                    }
-
-                    return isConstant(node.argument, false);
-
-                case "BinaryExpression":
-                    return isConstant(node.left, false) &&
-                            isConstant(node.right, false) &&
-                            node.operator !== "in";
-
-                case "LogicalExpression": {
-                    const isLeftConstant = isConstant(node.left, inBooleanPosition);
-                    const isRightConstant = isConstant(node.right, inBooleanPosition);
-                    const isLeftShortCircuit = (isLeftConstant && isLogicalIdentity(node.left, node.operator));
-                    const isRightShortCircuit = (inBooleanPosition && isRightConstant && isLogicalIdentity(node.right, node.operator));
-
-                    return (isLeftConstant && isRightConstant) ||
-                        isLeftShortCircuit ||
-                        isRightShortCircuit;
-                }
-                case "NewExpression":
-                    return inBooleanPosition;
-                case "AssignmentExpression":
-                    if (node.operator === "=") {
-                        return isConstant(node.right, inBooleanPosition);
-                    }
-
-                    if (["||=", "&&="].includes(node.operator) && inBooleanPosition) {
-                        return isLogicalIdentity(node.right, node.operator.slice(0, -1));
-                    }
-
-                    return false;
-
-                case "SequenceExpression":
-                    return isConstant(node.expressions[node.expressions.length - 1], inBooleanPosition);
-
-                // no default
-            }
-            return false;
-        }
-
         /**
          * Tracks when the given node contains a constant condition.
          * @param {ASTNode} node The AST node to check.
@@ -209,7 +62,7 @@ module.exports = {
          * @private
          */
         function trackConstantConditionLoop(node) {
-            if (node.test && isConstant(node.test, true)) {
+            if (node.test && isConstant(context.getScope(), node.test, true)) {
                 loopsInCurrentScope.add(node);
             }
         }
@@ -234,7 +87,7 @@ module.exports = {
          * @private
          */
         function reportIfConstant(node) {
-            if (node.test && isConstant(node.test, true)) {
+            if (node.test && isConstant(context.getScope(), node.test, true)) {
                 context.report({ node: node.test, messageId: "unexpected" });
             }
         }