Repository: eslint/eslint
File: lib/rules/complexity.js (JavaScript)

Code before:
            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,
            ChainExpression: increaseComplexity,
            AssignmentPattern: 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"

Review comment (performance):
This doesn't report the first example from https://github.com/eslint/eslint/issues/18060:

```js
/*eslint complexity: ["error", 2]*/

// still valid (calculated complexity = 2)
function a(x) {
    return x?.a?.b?.c?.d?.e?.f;
}

```

Because `x?.a?.b?.c?.d?.e?.f` is one `ChainExpression`. Perhaps we should count each `?.`?

Code after:
            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,
            AssignmentPattern: increaseComplexity,

            // Avoid `default`
            "SwitchCase[test]": increaseComplexity,

            // Logical assignment operators have short-circuiting behavior
            AssignmentExpression(node) {
                if (astUtils.isLogicalAssignmentOperator(node.operator)) {
                    increaseComplexity();
                }
            },

            MemberExpression(node) {
                if (node.optional === true) {
                    increaseComplexity();
                }
            },

            CallExpression(node) {
                if (node.optional === true) {
                    increaseComplexity();
                }
            },

            onCodePathEnd(codePath, node) {
                const complexity = complexities.pop();