Repository: eslint/eslint
File: lib/rules/for-direction.js (JavaScript)

Code before:
         * @param {string} counter variable name to check
         * @returns {int} if add return 1, if sub return -1, if nochange, return 0
         */
        function getAssignmentDirection(update, counter) {
            if (update.left.name === counter) {
                if (update.operator === "+=") {
                    return getRightDirection(update, 1);
                }
                if (update.operator === "-=") {
                    return getRightDirection(update, -1);
                }
            }
            return 0;
        }

        /**
         * get the counter position in test
         * @param {ASTNode} node the node to check
         * @returns {"left" | "right"} the position of the counter respect to BinaryExpression
         */
        function getCounterPosition(node) {
            if (node.update.type === "UpdateExpression" || node.update.type === "AssignmentExpression") {
                if (node.update.argument && node.update.argument.type === "Identifier") {
                    return node.test.left.name === node.update.argument.name ? "left" : "right";
                }
            }
            return "left";
        }

        return {
            ForStatement(node) {

                if (node.test && node.test.type === "BinaryExpression" && (node.test.left.type === "Identifier" || node.test.right.type === "Identifier") && node.update) {
                    const counterPosition = getCounterPosition(node);
                    const counter = node.test[counterPosition].name;
                    const operator = node.test.operator;
                    const update = node.update;

                    let wrongDirection;

                    if (operator === "<" || operator === "<=") {
                        wrongDirection = counterPosition === "left" ? -1 : 1;
                    } else if (operator === ">" || operator === ">=") {
                        wrongDirection = counterPosition === "left" ? 1 : -1;
                    } else {
                        return;
                    }

                    if (update.type === "UpdateExpression") {
                        if (getUpdateDirection(update, counter) === wrongDirection) {
                            report(node);

Review comment (suggestion):
This doesn't seem to cover AssignmentExpression:

```js
for(var i = 0; 10 > i; i-=1){} // should be error
```

and looks partially redundant with functions that check whether the names match afterward.

What do you think about updating ForStatement(node) to always check both sides instead:

```js
ForStatement(node) {

    if (node.test && node.test.type === "BinaryExpression" && node.update) {
        for (const counterPosition of ["left", "right"]) {
            if (node.test[counterPosition].type !== "Identifier") {
                continue;
            }

            const counter = node.test[counterPosition].name;
            // ...
        }
    }
}
```

Code after:
         * @param {string} counter variable name to check
         * @returns {int} if add return 1, if sub return -1, if nochange, return 0
         */
        function getAssignmentDirection(update, counter) {
            if (update.left.name === counter) {
                if (update.operator === "+=") {
                    return getRightDirection(update, 1);
                }
                if (update.operator === "-=") {
                    return getRightDirection(update, -1);
                }
            }
            return 0;
        }

        return {
            ForStatement(node) {

                if (node.test && node.test.type === "BinaryExpression" && node.update) {
                    for (const counterPosition of ["left", "right"]) {
                        if (node.test[counterPosition].type !== "Identifier") {
                            continue;
                        }

                        const counter = node.test[counterPosition].name;
                        const operator = node.test.operator;
                        const update = node.update;

                        let wrongDirection;

                        if (operator === "<" || operator === "<=") {
                            wrongDirection = counterPosition === "left" ? -1 : 1;
                        } else if (operator === ">" || operator === ">=") {
                            wrongDirection = counterPosition === "left" ? 1 : -1;
                        } else {
                            return;
                        }

                        if (update.type === "UpdateExpression") {
                            if (getUpdateDirection(update, counter) === wrongDirection) {
                                report(node);
                            }
                        } else if (update.type === "AssignmentExpression" && getAssignmentDirection(update, counter) === wrongDirection) {
                            report(node);
                        }
                    }
                }
            }
        };
    }
};