|                                                                                                                                                                     |  | /** * @fileoverview Counts the cyclomatic complexity of each function of the script. See http://en.wikipedia.org/wiki/Cyclomatic_complexity.
 * Counts the number of if, conditional, for, while, try, switch/case, * @author Patrick Brosset */
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");const { upperCaseFirst } = require("../shared/string-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */module.exports = {    meta: {        type: "suggestion",
        docs: {            description: "Enforce a maximum cyclomatic complexity allowed in a program",            recommended: false,            url: "https://eslint.org/docs/latest/rules/complexity"        },
        schema: [            {                oneOf: [                    {                        type: "integer",                        minimum: 0                    },                    {                        type: "object",                        properties: {                            maximum: {                                type: "integer",                                minimum: 0                            },                            max: {                                type: "integer",                                minimum: 0                            }                        },                        additionalProperties: false                    }                ]            }        ],
        messages: {            complex: "{{name}} has a complexity of {{complexity}}. Maximum allowed is {{max}}."        }    },
    create(context) {        const option = context.options[0];        let THRESHOLD = 20;
        if (            typeof option === "object" &&            (Object.prototype.hasOwnProperty.call(option, "maximum") || Object.prototype.hasOwnProperty.call(option, "max"))        ) {            THRESHOLD = option.maximum || option.max;        } else if (typeof option === "number") {            THRESHOLD = option;        }
        //--------------------------------------------------------------------------
        // Helpers
        //--------------------------------------------------------------------------
        // Using a stack to store complexity per code path
        const complexities = [];
        /**         * Increase the complexity of the code path in context         * @returns {void}         * @private         */        function increaseComplexity() {            complexities[complexities.length - 1]++;        }
        //--------------------------------------------------------------------------
        // Public API
        //--------------------------------------------------------------------------
        return {
            onCodePathStart() {
                // The initial complexity is 1, representing one execution path in the CodePath
                complexities.push(1);            },
            // Each branching in the code adds 1 to the complexity
            CatchClause: increaseComplexity,            ConditionalExpression: increaseComplexity,            LogicalExpression: increaseComplexity,            ForStatement: increaseComplexity,            ForInStatement: increaseComplexity,            ForOfStatement: increaseComplexity,            IfStatement: increaseComplexity,            WhileStatement: increaseComplexity,            DoWhileStatement: increaseComplexity,
            // Avoid `default`
            "SwitchCase[test]": increaseComplexity,
            // Logical assignment operators have short-circuiting behavior
            AssignmentExpression(node) {                if (astUtils.isLogicalAssignmentOperator(node.operator)) {                    increaseComplexity();                }            },
            onCodePathEnd(codePath, node) {                const complexity = complexities.pop();
                /*                 * This rule only evaluates complexity of functions, so "program" is excluded.                 * Class field initializers and class static blocks are implicit functions. Therefore,                 * they shouldn't contribute to the enclosing function's complexity, but their                 * own complexity should be evaluated.                 */                if (                    codePath.origin !== "function" &&                    codePath.origin !== "class-field-initializer" &&                    codePath.origin !== "class-static-block"                ) {                    return;                }
                if (complexity > THRESHOLD) {                    let name;
                    if (codePath.origin === "class-field-initializer") {                        name = "class field initializer";                    } else if (codePath.origin === "class-static-block") {                        name = "class static block";                    } else {                        name = astUtils.getFunctionNameWithKind(node);                    }
                    context.report({                        node,                        messageId: "complex",                        data: {                            name: upperCaseFirst(name),                            complexity,                            max: THRESHOLD                        }                    });                }            }        };
    }};
 |